flame icon indicating copy to clipboard operation
flame copied to clipboard

docs: document recommended approach for localization support

Open felangel opened this issue 2 years ago • 4 comments

What could be improved

As a developer, I want to be able to access localizable strings within my game and within my custom components so that any strings can be localized. I not aware of any documentation/recommended approaches regarding how this could be achieved and felt it could be an area of improvement in terms of documentation.

Why should this be improved

Flame games should support localization and should ideally be compatible with the recommended localization approach.

Any risks?

This is just a request for documentation/clarification on what the recommended approach is. One solution could be to inject an AppLocalizations instance into the custom FlameGame and then access that via the game ref across components. Not sure if there are better alternatives used by the flame community but it would be great to discuss approaches and document the recommended approach.

felangel avatar Mar 29 '22 17:03 felangel

Thanks for the suggestion! We definitely needs to improve on this area. Right, the recommended l10n approach is already possible as a Flame Game exposes the build context after it is attached, so to access the l10n from a component, it would just be a matter of doing like this:

class MyTextComponent extends TextComponent with HasGameRef<MyGame> {
  @override
  Future<void> onLoad() async {
    text = AppLocalizations.of(gameRef.buildContext).myKey;
  }
}

Things that could be improved here are:

  • Like mentioned on the description, mention this on the docs
  • Maybe offer some helpers as that line can get a little bit long?

erickzanardo avatar Mar 29 '22 18:03 erickzanardo

Things that could be improved here are:

* Like mentioned on the description, mention this on the docs

* Maybe offer some helpers as that line can get a little bit long?

We could make it as a bridge package maybe? So we don't "lock" people in on localization on the engine?

wolfenrain avatar Mar 30 '22 10:03 wolfenrain

Maybe offer some helpers as that line can get a little bit long?

User-defined getter in MyGame is sufficient for this

AppLocalizations get t => AppLocalizations.of(gameRef.buildContext);

Like mentioned on the description, mention this on the docs

This could go in a special "cookbook" collection of recipes, but we haven't started one yet.

st-pasha avatar Mar 30 '22 17:03 st-pasha

Found this i18n_extension package, which looks simple enough to not requiring any additional support from our side.

st-pasha avatar Jun 26 '22 21:06 st-pasha

This can be added in the community snippets that we have open in another issue.

munsterlander avatar Oct 09 '22 19:10 munsterlander

So, I looked through the standard internationalization library in Flutter, and also the i18n_extension -- and I came to the conclusion that they may not be well-suited for games.

The main use case of these libraries is a widget-based App with some simple buttons, labels, and occasional text messages. Thus, the number of elements to translate is both small and known at compile time.

The needs in games, however, are different. There are WAY more things to translate:

  • NPC names;
  • object names and descriptions;
  • dialogues;
  • quests;
  • books;
  • captions;
  • voice-overs;
  • certain images, like signs (?);
  • etc.

Moreover, many games allow downloadable content, so the content that needs to be translated would only be known at runtime. Also, since the translation data is large in size, it might be preferable to not bundle it with the game, but only download upon user request.

I think it might be better to investigate which l10n solutions exist for other game engines, and build a bridge package if possible.

st-pasha avatar Oct 25 '22 04:10 st-pasha

Hi, how can I managed to get translated as you mentioned? I'm new to flame game and dart, and I've looked into some localization toturials but they all required set some delegates like

@override Widget build(BuildContext context) { return MaterialApp( localizationsDelegates: [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, ], supportedLocales: [ const Locale('en', "US"), const Locale('pt', "BR"), ], home: I18n(child: ...) ); }

But in my main dart the game entry was like this: runApp(GameWidget(game: MyGame()));

It seems that the delegate must be initialized with in a MaterialApp but what a got is a GameWidget, you've mentioned that there's someway doable, but after a lot of searching I can't find a demo for the flame game, so could you please help me with this or send me some kind of torurials? Thanks

tommycloud avatar Jan 15 '23 11:01 tommycloud

@tommycloud just put the GameWidget as a child into the tree that you posted, instead of putting it directly in runApp

spydon avatar Jan 15 '23 13:01 spydon

Thank you @spydon , worked as charm Here's my code, in case some fresh like me needed

class MyApp extends StatelessWidget {

  var gameWidget;
  MyApp(this.gameWidget) : super();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        localizationsDelegates: context.localizationDelegates,
        supportedLocales: context.supportedLocales,
        locale: context.locale,
        home: gameWidget
    );
  }
}

tommycloud avatar Jan 15 '23 15:01 tommycloud

Another solution is slang. It doesn't depend on Flutter, so you can use it on your backend too.

With Translation Overrides you can load translations dynamically without sacrificing type-safety.

Disclaimer: I am author of this package.

Tienisto avatar Dec 02 '23 23:12 Tienisto

I think this can be closed, since you have access to the context and then can use the same solutions as in Flutter.

spydon avatar Dec 03 '23 01:12 spydon