This is a plugin for NativeScript that implements internationalization (i18n) using the native capabilities of each platform. It is inspired from nativescript-i18n
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 Committe and to vastly improve plugin maintenance it was scoped and moved here!
ns plugin add @nativescript/localize
Create a folder 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 error.
import { 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' }}"/>
import { localize } from '@nativescript/localize'
console.log(localize('Hello world !'))
const application = require('application')
const { localize } = require('@nativescript/localize')
application.setResources({ L: localize })
<Label text="{{ L('Hello world !') }}"/>
<Label text="{{ L('I am %s', 'user name') }}"/>
const { localize } = require('@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()
import { localize } from '@nativescript/localize'
Vue.filter('L', localize)
<label :text="'Hello world !'|L"></label> <label :text="'I am %s'|L('user name')"></label>
Each file is imported using require
, 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'
}
Add the .default
extension to the default language file to set it as the fallback language:
fr.default.json
The app.name
key is used to localize the application name:
{
"app.name": "My app"
}
Keys starting with ios.info.plist.
are used to localize iOS properties:
{
"ios.info.plist.NSLocationWhenInUseUsageDescription": "This will be added to InfoPlist.strings"
}
This plugin uses the native capabilities of each platform, language selection is therefore made by the OS.
import { overrideLocale } from '@nativescript/localize'
const localeOverriddenSuccessfully = overrideLocale('en-GB') // or "nl-NL", etc (or even just the part before the hyphen)
In your app.ts
/ main.ts
/ app.js
import { Application } from '@nativescript/core'
import { androidLaunchEventLocalizationHandler } from '@nativescript/localize'
Application.on(Application.launchEvent, args => {
if (args.android) {
androidLaunchEventLocalizationHandler()
}
})
And in your settings page where user chooses the language:
import { overrideLocale } from '@nativescript/localize'
const localeOverriddenSuccessfully = overrideLocale('en-GB') // or "nl-NL", etc (or even just the part before the hyphen)
Important
In both cases, after calling override Locale, you must ask the user to restart the app
For Example:
import { Application } 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) {
;(
Application.android.foregroundActivity || Application.android.startActivity
).finish()
} else {
exit(0)
}
})
Important
In case you are using Android app bundle to release your android app, add this 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 by using this
import { Device } from '@nativescript/core'
console.log("user's language is", Device.language.split('-')[0])
Tip
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);
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);
}
For unknown reasons, the very first creation of it resets the application locale to the device default. Therefore, you have to set the desired locale back. This is 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()
}
Apache License Version 2.0