Basics

Localization

Introduction

Localization allows you to provide your app in multiple languages. Nylo Website v7 makes it easy to localize text using JSON language files.

Here's a quick example:

lang/en.json

{
  "welcome": "Welcome",
  "greeting": "Hello {{name}}"
}

In your widget:

Text("welcome".tr())              // "Welcome"
Text("greeting".tr(arguments: {"name": "Anthony"}))  // "Hello Anthony"

Configuration

Localization is configured in lib/config/localization.dart:

final class LocalizationConfig {
  // Default language code (matches your JSON file, e.g., 'en' for lang/en.json)
  static final String languageCode =
      getEnv('DEFAULT_LOCALE', defaultValue: "en");

  // LocaleType.device - Use device's language setting
  // LocaleType.asDefined - Use languageCode above
  static final LocaleType localeType =
      getEnv('LOCALE_TYPE', defaultValue: 'asDefined') == 'device'
          ? LocaleType.device
          : LocaleType.asDefined;

  // Directory containing language JSON files
  static const String assetsDirectory = 'lang/';

  // List of supported locales
  static const List<Locale> supportedLocales = [
    Locale('en'),
    Locale('es'),
    // Add more locales as needed
  ];

  // Fallback when a key is not found in the active locale
  static const String fallbackLanguageCode = 'en';

  // RTL language codes
  static const List<String> rtlLanguages = ['ar', 'he', 'fa', 'ur'];

  // Log warnings for missing translation keys
  static final bool debugMissingKeys =
      getEnv('DEBUG_TRANSLATIONS', defaultValue: 'false') == 'true';
}

Adding Localized Files

Add your language JSON files to the lang/ directory:

lang/
├── en.json   # English
├── es.json   # Spanish
├── fr.json   # French
└── ...

lang/en.json

{
  "welcome": "Welcome",
  "settings": "Settings",
  "navigation": {
    "home": "Home",
    "profile": "Profile"
  }
}

lang/es.json

{
  "welcome": "Bienvenido",
  "settings": "Configuración",
  "navigation": {
    "home": "Inicio",
    "profile": "Perfil"
  }
}

Register in pubspec.yaml

Make sure your language files are included in your pubspec.yaml:

flutter:
  assets:
    - lang/

Localizing Text

Use the .tr() extension or the trans() helper to translate strings:

// Using the .tr() extension
"welcome".tr()

// Using the trans() helper
trans("welcome")

Nested Keys

Access nested JSON keys using dot notation:

lang/en.json

{
  "navigation": {
    "home": "Home",
    "profile": "Profile"
  }
}
"navigation.home".tr()       // "Home"
trans("navigation.profile")  // "Profile"

Arguments

Pass dynamic values into your translations using the {{key}} syntax:

lang/en.json

{
  "greeting": "Hello {{name}}",
  "items_count": "You have {{count}} items"
}
"greeting".tr(arguments: {"name": "Anthony"})
// "Hello Anthony"

trans("items_count", arguments: {"count": "5"})
// "You have 5 items"

Updating the Locale

Change the app's language at runtime:

// Using NyLocalization directly
await NyLocalization.instance.setLanguage(
  context,
  language: 'es'  // Must match your JSON filename (es.json)
);

If your widget extends NyPage, use the changeLanguage helper:

class _SettingsPageState extends NyPage<SettingsPage> {

  @override
  Widget view(BuildContext context) {
    return ListView(
      children: [
        ListTile(
          title: Text("English"),
          onTap: () => changeLanguage('en'),
        ),
        ListTile(
          title: Text("Español"),
          onTap: () => changeLanguage('es'),
        ),
      ],
    );
  }
}

Setting a Default Locale

Set the default language in your .env file:

DEFAULT_LOCALE="en"

Or use the device's locale by setting:

LOCALE_TYPE="device"

After changing .env, regenerate your environment config:

metro make:env --force

Supported Locales

Define which locales your app supports in LocalizationConfig:

static const List<Locale> supportedLocales = [
  Locale('en'),
  Locale('es'),
  Locale('fr'),
  Locale('de'),
  Locale('ar'),
];

This list is used by Flutter's MaterialApp.supportedLocales.

Fallback Language

When a translation key is not found in the active locale, Nylo Website falls back to the specified language:

static const String fallbackLanguageCode = 'en';

This ensures your app never shows raw keys if a translation is missing.

RTL Support

Nylo Website v7 includes built-in support for right-to-left (RTL) languages:

static const List<String> rtlLanguages = ['ar', 'he', 'fa', 'ur'];

// Check if current language is RTL
if (LocalizationConfig.isRtl(currentLanguageCode)) {
  // Handle RTL layout
}

Debug Missing Keys

Enable warnings for missing translation keys during development:

In your .env file:

DEBUG_TRANSLATIONS="true"

This logs warnings when .tr() cannot find a key, helping you catch untranslated strings.

NyLocalization API

NyLocalization is a singleton that manages all localization. Beyond the basic translate() method, it provides several additional methods:

Check if a Translation Exists

bool exists = NyLocalization.instance.hasTranslation('welcome');
// true if the key exists in the current language file

// Also works with nested keys
bool nestedExists = NyLocalization.instance.hasTranslation('navigation.home');

Get All Translation Keys

Useful for debugging to see which keys are loaded:

List<String> keys = NyLocalization.instance.getAllKeys();
// ['welcome', 'settings', 'navigation', ...]

Change Locale Without Restart

If you want to change the locale silently (without restarting the app):

await NyLocalization.instance.setLocale(locale: Locale('fr'));

This loads the new language file but does not restart the app. Useful when you want to handle UI updates manually.

Check RTL Direction

bool isRtl = NyLocalization.instance.isDirectionRTL(context);

Access Current Locale

// Get the current language code
String code = NyLocalization.instance.languageCode;  // e.g., 'en'

// Get the current Locale object
Locale currentLocale = NyLocalization.instance.locale;

// Get Flutter localization delegates (used in MaterialApp)
var delegates = NyLocalization.instance.delegates;

Full API Reference

Method / Property Returns Description
instance NyLocalization Singleton instance
translate(key, [arguments]) String Translate a key with optional arguments
hasTranslation(key) bool Check if a translation key exists
getAllKeys() List<String> Get all loaded translation keys
setLanguage(context, {language, restart}) Future<void> Change language, optionally restart
setLocale({locale}) Future<void> Change locale without restart
setDebugMissingKeys(enabled) void Enable/disable missing key logging
isDirectionRTL(context) bool Check if current direction is RTL
restart(context) void Restart the app
languageCode String Current language code
locale Locale Current Locale object
delegates Iterable<LocalizationsDelegate> Flutter localization delegates

NyLocaleHelper

NyLocaleHelper is a static utility class for locale operations. It provides methods for detecting the current locale, checking RTL support, and creating Locale objects.

// Get the current system locale
Locale locale = NyLocaleHelper.getCurrentLocale(context: context);

// Get language and country codes
String langCode = NyLocaleHelper.getLanguageCode(context: context);  // 'en'
String? countryCode = NyLocaleHelper.getCountryCode(context: context);  // 'US' or null

// Check if current locale matches
bool isEnglish = NyLocaleHelper.matchesLocale(context, 'en');
bool isUsEnglish = NyLocaleHelper.matchesLocale(context, 'en', 'US');

// RTL detection
bool isRtl = NyLocaleHelper.isRtlLanguage('ar');  // true
bool currentIsRtl = NyLocaleHelper.isCurrentLocaleRtl(context: context);

// Get text direction
TextDirection direction = NyLocaleHelper.getTextDirection('ar');  // TextDirection.rtl
TextDirection currentDir = NyLocaleHelper.getCurrentTextDirection(context: context);

// Create a Locale from strings
Locale newLocale = NyLocaleHelper.toLocale('en', 'US');

Full API Reference

Method Returns Description
getCurrentLocale({context}) Locale Get current system locale
getLanguageCode({context}) String Get current language code
getCountryCode({context}) String? Get current country code
matchesLocale(context, languageCode, [countryCode]) bool Check if current locale matches
isRtlLanguage(languageCode) bool Check if a language code is RTL
isCurrentLocaleRtl({context}) bool Check if current locale is RTL
getTextDirection(languageCode) TextDirection Get TextDirection for a language
getCurrentTextDirection({context}) TextDirection Get TextDirection for current locale
toLocale(languageCode, [countryCode]) Locale Create a Locale from strings

The rtlLanguages constant contains: ar, he, fa, ur, yi, ps, ku, sd, dv.

Changing Language from a Controller

If you use controllers with your pages, you can change the language from NyController:

class SettingsController extends NyController {

  void switchToSpanish() {
    changeLanguage('es');
  }

  void switchToEnglishNoRestart() {
    changeLanguage('en', restartState: false);
  }
}

The restartState parameter controls whether the app restarts after changing the language. Set it to false if you want to handle the UI update yourself.