Add Farsi(fa) language

This commit is contained in:
problematicconsumer
2023-07-08 23:16:22 +03:30
parent 4b0b1145ba
commit 5c23a75398
9 changed files with 237 additions and 59 deletions

View File

@@ -69,8 +69,9 @@
},
"settings": {
"pageTitle": "settings",
"appearance": {
"sectionTitle": "appearance",
"general": {
"sectionTitle": "general",
"locale": "language",
"themeMode": "theme mode",
"themeModes": {
"system": "follow system theme",

View File

@@ -0,0 +1,126 @@
{
"general": {
"appTitle": "هیدیفای",
"reset": "ریست",
"toggle": {
"enabled": "فعال",
"disabled": "غیر فعال"
}
},
"home": {
"pageTitle": "خانه",
"emptyProfilesMsg": "با افزودن پروفایل شروع کنید",
"noActiveProfileMsg": "انتخاب پروفایل",
"connection": {
"tapToConnect": "برای اتصال ضربه بزنید",
"connecting": "در حال اتصال",
"disconnecting": "در حال قطع اتصال",
"connected": "متصل"
}
},
"profile": {
"overviewPageTitle": "پروفایل‌ها",
"detailsPageTitle": "پروفایل",
"subscription": {
"traffic": "ترافیک",
"updatedTimeAgo": "بروزرسانی شده در ${timeago}",
"remaining": "باقی مانده",
"expired": "منقضی شده",
"noTraffic": "پایان ترافیک"
},
"add": {
"buttonText": "افزودن پروفایل جدید",
"fromClipboard": "افزودن از کلیپ‌بورد",
"scanQr": "اسکن QR کد",
"manually": "افزودن دستی",
"invalidUrlMsg": "لینک نامعتبر"
},
"update": {
"failureMsg": "در بروزرسانی پروفایل خطایی رخ داد: ${reason}",
"successMsg": "پروفایل با موفقیت بروزرسانی شد"
},
"delete": {
"buttonText": "حذف",
"confirmationMsg": "حذف پروفایل برای همیشه؟ این عمل قابل لغو نیست.",
"successMsg": "پروفایل با موفقیت حذف شد"
},
"save": {
"buttonText": "ذخیره",
"successMsg": "پروفایل با موفقیت ذخیره شد"
},
"detailsForm": {
"nameHint": "نام",
"urlHint": "لینک",
"emptyNameMsg": "نام نمیتواند خالی باشد",
"invalidUrlMsg": "لینک غیر معتبر"
}
},
"proxies": {
"pageTitle": "پراکسی‌ها",
"emptyProxiesMsg": "پراکسی وجود ندارد",
"delayTestTooltip": "تست تاخیر",
"cancelTestButtonText": "لغو تست"
},
"logs": {
"pageTitle": "لاگ‌ها",
"clearLogsButtonText": "پاک‌سازی",
"filterHint": "فیلتر",
"allLevelsFilter": "همه"
},
"settings": {
"pageTitle": "تنظیمات",
"general": {
"sectionTitle": "اصلی",
"locale": "زبان",
"themeMode": "تم مود",
"themeModes": {
"system": "پیروی از تم دستگاه",
"dark": "تم تیره",
"light": "تم روشن"
},
"trueBlack": "کاملا سیاه"
},
"network": {
"sectionTitle": "شبکه",
"systemProxy": "سیستم پراکسی",
"systemProxyMsg": "افزودن سیستم پراکسی به سرویس VPN",
"bypassPrivateNetworks": "عبور دادن شبکه خصوصی",
"bypassPrivateNetworksMsg": "عبور دادن آدرس‌های شبکه خصوصی"
},
"clash": {
"sectionTitle": "جاگزین‌های پراکسی کلش",
"doNotModify": "تغییر نده",
"overrides": {
"httpPort": "HTTP Port",
"socksPort": "Socks Port",
"redirPort": "Redirect Port",
"tproxyPort": "TProxy Port",
"mixedPort": "Mixed Port",
"allowLan": "Allow LAN",
"ipv6": "IPv6",
"mode": "Mode",
"logLevel": "Log Level"
}
}
},
"tray": {
"dashboard": "داشبورد",
"quit": "خروج",
"systemProxy": "پراکسی سیستم"
},
"failure": {
"unexpected": "خطایی رخ داده",
"clash": {
"unexpected": "خطایی رخ داده",
"core": "خطای کلش ${reason}"
},
"connectivity": {
"unexpected": "خطایی رخ داده"
},
"profiles": {
"unexpected": "خطایی رخ داده",
"notFound": "پروفایل یافت نشد",
"invalidConfig": "کانفیگ غیر معتبر"
}
}
}

View File

@@ -5,7 +5,8 @@ import 'package:hiddify/gen/translations.g.dart';
export 'package:hiddify/gen/translations.g.dart';
enum LocalePref {
en;
en,
fa;
Locale get locale {
return Locale(name);

View File

@@ -25,7 +25,7 @@ class SettingsPage extends HookConsumerWidget {
child: ListView(
children: [
_SettingsSectionHeader(
t.settings.appearance.sectionTitle.titleCase,
t.settings.general.sectionTitle.titleCase,
),
const AppearanceSettingTiles(),
divider,

View File

@@ -1,54 +0,0 @@
import 'package:flutter/material.dart';
import 'package:hiddify/core/core_providers.dart';
import 'package:hiddify/core/theme/theme.dart';
import 'package:hiddify/features/settings/widgets/theme_mode_switch_button.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:recase/recase.dart';
class AppearanceSettingTiles extends HookConsumerWidget {
const AppearanceSettingTiles({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final t = ref.watch(translationsProvider);
final theme = ref.watch(themeControllerProvider);
final themeController = ref.watch(themeControllerProvider.notifier);
return Column(
children: [
ListTile(
title: Text(t.settings.appearance.themeMode.titleCase),
subtitle: Text(
switch (theme.themeMode) {
ThemeMode.system => t.settings.appearance.themeModes.system,
ThemeMode.light => t.settings.appearance.themeModes.light,
ThemeMode.dark => t.settings.appearance.themeModes.dark,
}
.sentenceCase,
),
trailing: ThemeModeSwitch(
themeMode: theme.themeMode,
onChanged: (value) {
themeController.change(themeMode: value);
},
),
onTap: () async {
await themeController.change(
themeMode: Theme.of(context).brightness == Brightness.light
? ThemeMode.dark
: ThemeMode.light,
);
},
),
SwitchListTile(
title: Text(t.settings.appearance.trueBlack.titleCase),
value: theme.trueBlack,
onChanged: (value) {
themeController.change(trueBlack: value);
},
),
],
);
}
}

View File

@@ -0,0 +1,95 @@
import 'package:flutter/material.dart';
import 'package:flutter_localized_locales/flutter_localized_locales.dart';
import 'package:go_router/go_router.dart';
import 'package:hiddify/core/core_providers.dart';
import 'package:hiddify/core/locale/locale.dart';
import 'package:hiddify/core/theme/theme.dart';
import 'package:hiddify/features/settings/widgets/theme_mode_switch_button.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:recase/recase.dart';
class AppearanceSettingTiles extends HookConsumerWidget {
const AppearanceSettingTiles({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final t = ref.watch(translationsProvider);
final locale = ref.watch(localeControllerProvider);
final theme = ref.watch(themeControllerProvider);
final themeController = ref.watch(themeControllerProvider.notifier);
return Column(
children: [
ListTile(
title: Text(t.settings.general.locale.titleCase),
subtitle: Text(
LocaleNamesLocalizationsDelegate.nativeLocaleNames[locale.name] ??
locale.name,
),
onTap: () async {
final selectedLocale = await showDialog<LocalePref>(
context: context,
builder: (context) {
return SimpleDialog(
title: Text(t.settings.general.locale.titleCase),
children: LocalePref.values
.map(
(e) => RadioListTile(
title: Text(
LocaleNamesLocalizationsDelegate
.nativeLocaleNames[e.name] ??
e.name,
),
value: e,
groupValue: locale,
onChanged: (e) => context.pop(e),
),
)
.toList(),
);
},
);
if (selectedLocale != null) {
await ref
.read(localeControllerProvider.notifier)
.change(selectedLocale);
}
},
),
ListTile(
title: Text(t.settings.general.themeMode.titleCase),
subtitle: Text(
switch (theme.themeMode) {
ThemeMode.system => t.settings.general.themeModes.system,
ThemeMode.light => t.settings.general.themeModes.light,
ThemeMode.dark => t.settings.general.themeModes.dark,
}
.sentenceCase,
),
trailing: ThemeModeSwitch(
themeMode: theme.themeMode,
onChanged: (value) {
themeController.change(themeMode: value);
},
),
onTap: () async {
await themeController.change(
themeMode: Theme.of(context).brightness == Brightness.light
? ThemeMode.dark
: ThemeMode.light,
);
},
),
SwitchListTile(
title: Text(t.settings.general.trueBlack.titleCase),
value: theme.trueBlack,
onChanged: (value) {
themeController.change(trueBlack: value);
},
),
],
);
}
}

View File

@@ -1,3 +1,3 @@
export 'appearance_setting_tiles.dart';
export 'clash_setting_tiles.dart';
export 'general_setting_tiles.dart';
export 'network_setting_tiles.dart';

View File

@@ -483,6 +483,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_localized_locales:
dependency: "direct main"
description:
name: flutter_localized_locales
sha256: f219350dffcfd56692b4e41953710c2975888dd9c507d977ec6853d7ea140336
url: "https://pub.dev"
source: hosted
version: "2.0.4"
flutter_loggy:
dependency: "direct main"
description:

View File

@@ -76,6 +76,7 @@ dependencies:
sliver_tools: ^0.2.10
flutter_adaptive_scaffold: ^0.1.5
fl_chart: ^0.63.0
flutter_localized_locales: ^2.0.4
dev_dependencies:
flutter_test: