A plugin that implements internationalization (i18n) using the native capabilities of each platform. It is inspired by nativescript-i18n
To install the plugin, run the following command in the root directory of your project.
npm install @nativescript/localize
This section describes how to use the @nativescript/localize
plugin in several flavors that NativeScript supports.
i18n
in the app
folder, with the following structure:app
| i18n
| en.json <-- english language
| es.default.json <-- spanish language (default)
es.default.json
example:
{
"app.name": "Comida Rica!",
"user": {
"name": "Paula"
}
}
main.ts
file, register the localize
function with the setResources
method of the Appilcation class, as follows.import { Application } from '@nativescript/core'
import { localize } from '@nativescript/localize'
Application.setResources({ L: localize })
Then, use the L
property in the markup.
<StackLayout>
<Label text="{{ 'Hello world !' | L }}" />
<Label text="{{ 'I am ' + L('user.name') }}" />
</StackLayout>
To localize in code-behind, just call the localize
method directly.
import { localize } from '@nativescript/localize'
console.log(localize('Hello world !'))
⚠️ If you notice translations work on your main XML page, but don't work on a page you navigate to, then add this little hack to the 'page loaded' function of that new page:
const page = args.object
page.bindingContext = new Observable()
i18n
in the src
folder, with the following structure:src
| i18n
| en.json <-- english language
| fr.default.json <-- french language (default)
| es.js
You need to set the default langage and make sure it contains the application name to avoid any errors.
NativeScriptLocalizeModule
) in the app.module.ts
fileimport { NgModule, NO_ERRORS_SCHEMA } from '@angular/core'
import { NativeScriptLocalizeModule } from '@nativescript/localize/angular'
import { NativeScriptModule } from '@nativescript/angular'
import { AppComponent } from './app.component'
@NgModule({
declarations: [AppComponent],
bootstrap: [AppComponent],
imports: [NativeScriptModule, NativeScriptLocalizeModule],
schemas: [NO_ERRORS_SCHEMA]
})
export class AppModule {}
<Label text="{{ 'Hello world !' | L }}"/>
<Label text="{{ 'I am %s' | L:'user name' }}"/>
i18n
in the app
folder, with the following structure:app
| i18n
| en.json <-- english language
| es.default.json <-- spanish language (default)
es.default.json
example:
{
"app.name": "Comida Rica!",
"user": {
"name": "Paula"
}
}
import { localize } from '@nativescript/localize'
<ActionBar>
<Label :text="localize('app.name')" class="font-bold text-lg bg-black" />
</ActionBar>
<StackLayout class="px-4">
<Label :text="localize('user.name')" textWrap="true" />
</StackLayout>
i18n
in the app
folder, with the following structure:app
| i18n
| en.json <-- english language
| es.default.json <-- spanish language (default)
es.default.json
example:
{
"app.name": "Comida Rica!",
"user": {
"name": "Paula"
}
}
import { localize } from '@nativescript/localize'
<actionBar>
<label text={ localize('app.name') } class="font-bold text-lg bg-black" />
</actionBar>
<stackLayout class="px-4">
<label text={ 'Nombre: ' + localize('user.name')}/>
</stackLayout>
To set the default language, add a .default
extension to the name of the default language file.
fr.default.json
Make sure it contains the application name to avoid any errors.
Android uses the locale file corresponding to the device's language. For example, if the device's language is set to Spanish
, the es.json
will be used.
To localize the application name, use the app.name
key.
{
"app.name": "My app"
}
Each file is imported using require
, so use the file format of your choice:
{
"app.name": "My app",
"ios.info.plist": {
"NSLocationWhenInUseUsageDescription": "This will be added to InfoPlist.strings"
},
"user": {
"name": "user.name",
"email": "user.email"
},
"array": ["split the translation into ", "multiples lines"],
"sprintf": "format me %s",
"sprintf with numbered placeholders": "format me %2$s one more time %1$s"
}
export const i18n = {
'app.name': 'My app'
}
To localize an iOS property, prefix it with ios.info.plist.
. The example below shows how to localize the NSLocationWhenInUseUsageDescription property.
{
"ios.info.plist.NSLocationWhenInUseUsageDescription": "This will be added to InfoPlist.strings"
}
To change the language dynamically at runtime, use the overrideLocale method.
import { overrideLocale } from '@nativescript/localize'
const localeOverriddenSuccessfully = overrideLocale('en-GB') // or "nl-NL", etc (or even just the part before the hyphen)
For Android, first, call the androidLaunchEventLocalizationHandler
method in the launchEvent
handler, in the main.ts
file.
import { Application } from '@nativescript/core'
import { androidLaunchEventLocalizationHandler } from '@nativescript/localize'
Application.on(Application.launchEvent, args => {
if (args.android) {
androidLaunchEventLocalizationHandler()
}
})
Then, in your settings page where the user chooses the language, call the overrideLocale
method:
import { overrideLocale } from '@nativescript/localize'
const localeOverriddenSuccessfully = overrideLocale('en-GB') // or "nl-NL", etc (or even just the part before the hyphen)
Important
On both platforms, after calling overrideLocale
method, you must ask the user to restart the app.
For Example:
import { Application, Utils } from '@nativescript/core'
import { overrideLocale } from '@nativescript/localize'
alert({
title: 'Switch Language',
message: 'The application needs to be restarted to change language',
okButtonText: 'Quit!'
}).then(() => {
L.localize.overrideLocale(selectedLang)
if (isAndroid) {
Utils.android.getCurrentActivity().finish()
} else {
exit(0)
}
})
Important
In case you are using Android app bundle to release your android app, add the following to App_Resources/Android/app.gradle
to make sure all lanugages are bundled in the split apks
android {
// there maybe other code here //
bundle {
language {
enableSplit = false
}
}
}
Tip
you can get the default language on user's phone via the language
property of the Device class.
import { Device } from '@nativescript/core'
console.log("user's language is", Device.language.split('-')[0])
Tip
The overrideLocale
method stores the language in a special key in app-settings, you can access it like this
import { ApplicationSettings } from '@nativescript/core'
console.log(ApplicationSettings.getString('__app__language__')) // only available after the first time you use overrideLocale(langName);
The angular localization pipe does not work when in a modal context. As a workaround, you can trigger a change detection from within your component constructor:
constructor(
private readonly params: ModalDialogParams,
private readonly changeDetectorRef: ChangeDetectorRef,
) {
setTimeout(() => this.changeDetectorRef.detectChanges(), 0);
}
On Android N+, the first creation of a WebView resets the application locale to the device default. Therefore, you have to set the desired locale back. This is a native bug and the workaround is
<WebView url="https://someurl.com" @loaded="webViewLoaded"/>
import {
overrideLocale,
androidLaunchEventLocalizationHandler
} from '@nativescript/localize'
import { ApplicationSettings } from '@nativescript/core'
const locale = ApplicationSettings.getString('__app__language__')
function webViewLoaded() {
overrideLocale(locale)
androidLaunchEventLocalizationHandler()
}
The plugin provides the following functions.
localizeString: string = localize(key, ...args)
Retrieves the translation for the specified key
from a .json
file in the i18n
directory.
isLocaleOverwritten: boolean = overrideLocale(locale)
Overrides the current locale with the specified locale
parameter.
androidLaunchEventLocalizationHandler()
A lot of thanks goes out to Ludovic Fabrèges (@lfabreges) for developing and maintaining this plugin in the past. When he had to abandon it due to shifted priorities, he was kind enough to move the repo to me. Eddy then joined NativeScript's Technical Steering Committee and to vastly improve plugin maintenance it was scoped and moved here
Apache License Version 2.0