Add Farsi(fa) language
This commit is contained in:
@@ -69,8 +69,9 @@
|
|||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"pageTitle": "settings",
|
"pageTitle": "settings",
|
||||||
"appearance": {
|
"general": {
|
||||||
"sectionTitle": "appearance",
|
"sectionTitle": "general",
|
||||||
|
"locale": "language",
|
||||||
"themeMode": "theme mode",
|
"themeMode": "theme mode",
|
||||||
"themeModes": {
|
"themeModes": {
|
||||||
"system": "follow system theme",
|
"system": "follow system theme",
|
||||||
|
|||||||
126
assets/translations/strings_fa.i18n.json
Normal file
126
assets/translations/strings_fa.i18n.json
Normal 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": "کانفیگ غیر معتبر"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,8 @@ import 'package:hiddify/gen/translations.g.dart';
|
|||||||
export 'package:hiddify/gen/translations.g.dart';
|
export 'package:hiddify/gen/translations.g.dart';
|
||||||
|
|
||||||
enum LocalePref {
|
enum LocalePref {
|
||||||
en;
|
en,
|
||||||
|
fa;
|
||||||
|
|
||||||
Locale get locale {
|
Locale get locale {
|
||||||
return Locale(name);
|
return Locale(name);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class SettingsPage extends HookConsumerWidget {
|
|||||||
child: ListView(
|
child: ListView(
|
||||||
children: [
|
children: [
|
||||||
_SettingsSectionHeader(
|
_SettingsSectionHeader(
|
||||||
t.settings.appearance.sectionTitle.titleCase,
|
t.settings.general.sectionTitle.titleCase,
|
||||||
),
|
),
|
||||||
const AppearanceSettingTiles(),
|
const AppearanceSettingTiles(),
|
||||||
divider,
|
divider,
|
||||||
|
|||||||
@@ -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);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
95
lib/features/settings/widgets/general_setting_tiles.dart
Normal file
95
lib/features/settings/widgets/general_setting_tiles.dart
Normal 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);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
export 'appearance_setting_tiles.dart';
|
|
||||||
export 'clash_setting_tiles.dart';
|
export 'clash_setting_tiles.dart';
|
||||||
|
export 'general_setting_tiles.dart';
|
||||||
export 'network_setting_tiles.dart';
|
export 'network_setting_tiles.dart';
|
||||||
|
|||||||
@@ -483,6 +483,14 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
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:
|
flutter_loggy:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ dependencies:
|
|||||||
sliver_tools: ^0.2.10
|
sliver_tools: ^0.2.10
|
||||||
flutter_adaptive_scaffold: ^0.1.5
|
flutter_adaptive_scaffold: ^0.1.5
|
||||||
fl_chart: ^0.63.0
|
fl_chart: ^0.63.0
|
||||||
|
flutter_localized_locales: ^2.0.4
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user