没有上下文的颤振本地化

时间:2020-05-02 16:52:58

标签: flutter localization

我正在尝试将我的应用本地化。我为支持的语言创建了所需的string.arb文件。

AppLocalizations.of(context)为什么需要上下文?

我只是想访问文件/语言环境文件/类中的命名字符串。 在应用程序中的某个时候,我建立了一个列表,稍后通过使用单独的类覆盖某些字段来填充它。

但是,该类没有上下文,但是我想在其中使用本地化的字符串。 我可以写一个方法让我输入的任何字符串都本地化吗?

4 个答案:

答案 0 :(得分:5)

如果您不想使用软件包,那么这里有一个对我有用的解决方案。现在,我见过的AppLocalizations中最多的common implementation通常有以下两行:

//.........
static const LocalizationsDelegate<AppLocalizations> delegate =
      _AppLocalizationsDelegate();

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

委托的实现如下所示:

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

  @override
  Future<AppLocalizations> load(Locale locale) async {
    AppLocalizations localizations = new AppLocalizations(locale);
    await localizations.load();

    return localizations;
  }

  //... the rest omitted for brevity
}

请注意,委托上的load方法将返回Future<AppLocalizations>。通常,从main调用一次load方法,然后再调用一次,因此您可以通过向委托添加AppLocalizations的静态实例来利用该方法。所以现在您的代表看起来像这样:

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

  static AppLocalizations instance;

  @override
  Future<AppLocalizations> load(Locale locale) async {
    AppLocalizations localizations = new AppLocalizations(locale);
    await localizations.load();

    instance = localizations; // set the static instance here

    return localizations;
  }

  //... the rest omitted for brevity
}

然后在您的AppLocalizations班上,您将拥有:

//.........
static const LocalizationsDelegate<AppLocalizations> delegate =
      _AppLocalizationsDelegate();

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

static AppLocalizations get instance => _AppLocalizationsDelegate.instance; // add this
//.........

现在,在您的翻译助手方法中,您可以:

String tr(String key) {
    return AppLocalizations.instance.translate(key);
}

不需要上下文。

答案 1 :(得分:0)

有一个名为easy_localization的库,它无需上下文即可进行本地化,您可以简单地使用该库。库还提供了更方便的方法,可编写更少的代码并仍然本地化应用程序的所有部分。主类示例:

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
  ]).then((_) {
    runApp(EasyLocalization(
      child: MyApp(),
      useOnlyLangCode: true,
      startLocale: Locale('nl'),
      fallbackLocale: Locale('nl'),
      supportedLocales: [
        Locale('nl'),
        Locale('en'),
      ],
      path: 'lang',
    ));
  });
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SplashScreen(),
      supportedLocales: EasyLocalization.of(context).supportedLocales,
      locale: EasyLocalization.of(context).locale,
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
        DefaultCupertinoLocalizations.delegate,
        EasyLocalization.of(context).delegate,
      ],
      localeResolutionCallback: (locale, supportedLocales) {
        if (locale == null) {
          EasyLocalization.of(context).locale = supportedLocales.first;
          Intl.defaultLocale = '${supportedLocales.first}';
          return supportedLocales.first;
        }

        for (Locale supportedLocale in supportedLocales) {
          if (supportedLocale.languageCode == locale.languageCode) {
            EasyLocalization.of(context).locale = supportedLocale;
            Intl.defaultLocale = '$supportedLocale';
            return supportedLocale;
          }
        }

        EasyLocalization.of(context).locale = supportedLocales.first;
        Intl.defaultLocale = '${supportedLocales.first}';
        return supportedLocales.first;
      },
    );
  }
}

也不要忘记将本地化路径添加到您的pubspec.yamal文件中!

完成所有这些操作后,您可以像这样在Text小部件中使用它即可:

Text(tr('someJsonKey'),),

答案 2 :(得分:0)

就我而言,我使用的是最小国际化版本。

根据 Minimal internationalization version 调整 chinloyal 的回答。

应用 chinloyal 的解决方案,但有以下区别:

从这里:

  @override
  Future<AppLocalizations> load(Locale locale) {
    return SynchronousFuture<AppLocalizations>(AppLocalizations(locale));
  }

为此:

  @override
  Future<AppLocalizations> load(Locale locale) async {
    var localizations =
        await SynchronousFuture<AppLocalizations>(AppLocalizations(locale));

    instance = localizations; // set the static instance here

    return localizations;
  }

答案 3 :(得分:0)

我们可以通过使用 get_it 轻松解决这个问题,我们可以在此设置后的任何地方使用该字符串。

  1. 将此安装到您的 vscode Flutter Intl VSCode Extension

  2. 设置pubspec.yaml

    dependencies:
    flutter:
      sdk: flutter
    flutter_localizations:                          # Add this line
      sdk: flutter                                  # Add this line
    intl: ^0.17.0                                   # Add this line
    get_it: ^7.2.0                                  # Add this line
    
    
    flutter:
      uses-material-design: true
      generate: true                                # Add this line
    
    
    flutter_intl:                                   # Add this line
      enabled: true                                 # Add this line
      class_name: I10n                              # Add this line
      main_locale: en                               # Add this line
      arb_dir: lib/core/localization/l10n           # Add this line
      output_dir: lib/core/localization/generated   # Add this line
    
  3. 设置 main.dart

    import 'package:component_gallery/core/localization/generated/l10n.dart';
    import 'package:component_gallery/locator.dart';
    import 'package:component_gallery/ui/pages/home.dart';
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter_localizations/flutter_localizations.dart';
    
    void main() {
      setupLocator();
      runApp(App());
    }
    
    class App extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          localizationsDelegates: [
            I10n.delegate,
            GlobalMaterialLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate,
            GlobalCupertinoLocalizations.delegate,
          ],
          supportedLocales: I10n.delegate.supportedLocales,
          localeResolutionCallback: (deviceLocale, supportedLocales) {
            if (supportedLocales
                .map((e) => e.languageCode)
                .contains(deviceLocale?.languageCode)) {
              return deviceLocale;
            } else {
              return const Locale('en', '');
            }
          },
          home: HomePage(),
        );
      }
    }
    
  4. 设置locator.dart

    import 'package:component_gallery/core/services/navigation_service.dart';
    import 'package:get_it/get_it.dart';
    
    GetIt locator = GetIt.instance;
    
    void setupLocator() {
      locator.registerLazySingleton(() => I10n());
    }
    
    
  5. 在没有上下文的情况下与 Get_it 一起使用

    final I10n _i10n = locator<I10n>();
    class MessageComponent extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Text(
          _i10n.sample,
          textAlign: TextAlign.center,
        );
      }
    }