6

到目前为止,我使用的是动态字符串,如这篇文章的解决方案所示: Flutter internationalization - Dynamic strings

这是一个例子:

AppLocalizations.of(context).userAge(18)

在 AppLocalizations.dart 上:

userAge(age) => Intl.message(
  "My age is $age",
  name: "userAge",
  args: [age]);
// Return "My age is 18"

但后来我读了这篇关于颤振国际化的文章:https ://medium.com/flutter-community/flutter-internationalization-the-easy-way-using-provider-and-json-c47caa4212b2 其中显示了如何使用 json 文件进行本地化字符串的资源文件。它看起来更方便,所以我更喜欢使用这种方法,但不知道如何从 json 文件中获取具有动态值的字符串。

有什么解决办法吗?

4

4 回答 4

9

要从 JSON 文件中获取具有动态值的字符串,您可以使用

final age = 18 //user input.
final ageString = 'user_age'
                   .localisedString()
                   .replaceAll(new RegExp(r'\${age}'), age)

en.json

{
  "user_age": "My age is ${age}",
  "user_name_age": "My name is ${name} and age is ${age}"
}

string_extension.dart

extension Localisation on String {
  String localisedString() {
    return stringBy(this) ?? '';
  }
}

另外,你可以做类似的事情,

  String localisedString(Map<String, String> args) {
      String str = localisedString();
      args.forEach((key, value) { 
        str = str.replaceAll(new RegExp(r'\${'+key+'}'), value);
      });
      return str;
  }
  
  //usecase
  final userName = 'Spider Man'
  final age = '18'
  final nameAgeString = 'user_name_age'.localisedString({'name': userName, 'age': age})

app_localisation.dart

Map<String, dynamic> _language;

String stringBy(String key) => _language[key] as String ?? 'null';

class AppLocalisationDelegate extends LocalizationsDelegate {
  const AppLocalisationDelegate();

  // override the following method if you want to specify the locale you are supporting.
  final _supportedLocale = ['en'];
  @override
  bool isSupported(Locale locale) => _supportedLocale.contains(locale.languageCode);

  @override
  Future load(Locale locale) async {
    String jsonString = await rootBundle
        .loadString("assets/strings/${locale.languageCode}.json");

    _language = jsonDecode(jsonString) as Map<String, dynamic>;
    print(_language.toString());
    return SynchronousFuture<AppLocalisationDelegate>(
        AppLocalisationDelegate());
  }

  @override
  bool shouldReload(AppLocalisationDelegate old) => false;
}
于 2020-06-19T10:06:23.610 回答
7
  1. json在您的目录中创建一个文件夹assets。将您的语言文件放入其中。

    assets
      json
       - en.json // for English 
       - ru.json  // for Russian
    
  2. 现在en.json,例如,写下你的字符串。

    {
      "myAge": "My age is"
    }
    

    同样,在 中ru.json

    {
      "myAge": "Мой возраст"
    }
    
  3. 将此添加到pubspec.yaml文件中(注意空格)

    flutter:
    
      uses-material-design: true
    
      assets:
        - assets/json/
    

    flutter pub get


初步工作完成。让我们转到代码方面。

将此样板代码复制到您的文件中:

Map<String, dynamic> language;

class AppLocalizations {
  static AppLocalizations of(BuildContext context) {
    return Localizations.of<AppLocalizations>(context, AppLocalizations);
  }

  String getText(String key) => language[key];

  String userAge(int age) => '${getText('myAge')} $age';
}

class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
  const AppLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) => ['en', 'ru'].contains(locale.languageCode);

  @override
  Future<AppLocalizations> load(Locale locale) async {
    final string = await rootBundle.loadString('assets/json/${locale.languageCode}.json');
    language = json.decode(string);
    return SynchronousFuture<AppLocalizations>(AppLocalizations());
  }

  @override
  bool shouldReload(AppLocalizationsDelegate old) => false;
}

在小部件中设置一些东西MaterialApp

void main() {
  runApp(
    MaterialApp(
      locale: Locale('ru'), // switch between "en" and "ru" to see effect
      localizationsDelegates: [const AppLocalizationsDelegate()],
      supportedLocales: [const Locale('en'), const Locale('ru')],
      home: HomePage(),
    ),
  );
}

现在,您可以简单地使用上面的委托:

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var age = AppLocalizations.of(context).userAge(18);
    // prints "My age is 18" for 'en' and "Мой возраст 18" for 'ru' locale. 
    print(age); 

    return Scaffold();
  }
}
于 2020-06-13T16:04:06.040 回答
4

我尝试了各种解决方案来实现本地化,我遇到的最好的是Localizely.com(非附属)制作的用于VS CodeAndroid Studio/IntelliJ的 Flutter Intl 插件。

有了它,基本上你使用市场/插件库安装插件,然后使用菜单选项为你的项目初始化。这会在 lib/l10n/intl_en.arb 中创建一个默认的英语语言环境(这听起来很吓人,但实际上只是 JSON),并在lib/generated.

您还必须将以下内容添加到您的依赖项中。

flutter_localizations:
    sdk: flutter

然后,您可以将密钥添加到此文件,它们将在您的应用程序中自动可用,方法是导入generated/l10n.dart包含名为 S 的类。

要使用它,无论您在哪里初始化 MaterialApp,请确保将其传递给 MaterialApp 的 localizationsDelegates 参数(很可能作为带有,和可能S.delegate的数组的一部分。)您还必须添加到 MaterialApp 的.GlobalMaterialLocalizations.delegateGlobalWidgetsLocalizations.delegateGlobalCupertinoLocalizations.delegateS.delegate.supportedLocalessupportedLocales

要添加更多语言环境,请使用菜单中的选项(至少在 intellij 中)或简单地创建更多 intl_.arb 文件,插件将自动识别并设置相关代码。

假设您有一个 intl_en 文件,其中包含以下内容:

{ "name": "Name" }

然后S.of(context).name,您将在代码中使用该字符串。

所有这一切在localizely的网站上都有更雄辩的解释。


现在,要在这些 .arb 文件中使用密钥,您只需将其包装在 {...} 中。例如:

{ "choose1OfNumOptions": "Choose 1 of {numoptions} options" }

会导致使用S.of(context).choose1OfNumOptions(numOptions);. 我不知道该插件是否支持完整的ARB 规范,但它至少支持基础知识。

另外,我没有使用 Localizely,但它似乎是管理翻译和插件自动集成的一种非常有用的方式,尽管我认为它的价格也非常高得吓人——至少对于我的应用程序来说,它恰好有大量的文字。实际上,我只有一个谷歌表,我在其中存储了所有翻译,当需要更新它时,我将其下载为 .tsv 并编写了一个简单的小解析器来写出 .arb 文件。

于 2020-06-19T08:47:23.823 回答
3

颤振本地化:

app_en.arb:

{
  "contactDetailsPopupEmailCopiedMessage": "Copied {email} to clipboard",
  "@contactDetailsPopupEmailCopiedMessage": {
    "description": "Message being displayed in a snackbar upon long-clicking email in contact details popup",
    "placeholders": {
      "email": {
        "type": "String",
        "example": "example@gmail.com"
      }
    }
  }
}

app_localizations.dart:

abstract class AppLocalizations {
  /// Message being displayed in a snackbar upon long-clicking email in contact details popup
  ///
  /// In en, this message translates to:
  /// **'Copied {email} to clipboard'**
  String contactDetailsPopupEmailCopiedMessage(String email);
}

用法:

l10n.contactDetailsPopupEmailCopiedMessage("example@gmail.com")

有关更多详细信息,请查看此处

于 2021-04-26T20:07:41.893 回答