Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
react-native-l20n
Advanced tools
Experimental adaptation of Mozilla's L20n localization framework for use within React Native.
npm install --save react-native-l20n
import React, {Component} from 'react';
import {View, Text} from 'react-native';
import L20n, {ftl} from 'react-native-l20n';
const l20n = L20n.create({
en: ftl`
product = react-native-l20n
welcome = Welcome, {$name}, to {product}!
description =
| {product} makes it possible to harness the forward-thinking
| design of Mozilla's L20n in an idiomatic fashion.
stars = This repository has {$count ->
[0] no stars
[1] one star
*[other] {$count} stars
} on GitHub.
`,
es: ftl`
welcome = Bienvenidos, {$name}, a {product}!
`,
});
class Example extends Component {
render() {
return (
<View>
<Text style={{fontWeight: 'bold'}}>
{l20n.welcome({name: 'James'})}
</Text>
<Text>
{l20n.description()}
</Text>
<Text>
{l20n.stars({count: 1000})}
</Text>
</View>
);
}
}
Mozilla has decades of experience shipping localized products. The design of
L20n reflects this accumulation of experience, and manages to deliver a format
as powerful as ICU MessageFormat
,
but as simple as gettext
.
If these comparisons mean nothing to you, perhaps it will suffice to say that L20n makes it easy to isolate the strings in your application, perform basic variable substitutions, and handle language nuances like pluralization, gender, and declension.
You don't take my word for it, though. Here are three excellent resources for getting started with L20n:
Learn the syntax with this quick step-by-step guide.
Tinker with framework with this browser-based IDE.
Read about the decisions that underpin the powerful, asymmetric design of the framework in this blog post.
The main drawback of L20n, from my perspective, is that it takes a heavy
dependency upon the DOM as its formal interface. Just as StyleSheet
brought
the best of CSS for use in React Native, this module decouples L20n from the
DOM and makes it available to your React Native app through a familiar,
idiomatic interface.
The first similarity to StyleSheet
is that L20n translations are meant to be
declared within the component they're used, alongside styles. For example:
const styles = StyleSheet.create({...});
const l20n = L20n.create({...});
As a consequence, nothing in the React Native implementation of L20n is asynchronous, which means that the interface for accessing translations is a simple, synchronous function that returns a string, like such:
render() {
return (
<Text style={styles.text}>
{l20n.helloWorld()}
</Text>
);
}
As seen in this example, the React Native implementation of L20n does not
utilize data
attributes (or any annotations in the virtual DOM or JSX) to
look up translations; it's just simple function calls, which means it can be
used with any component, builtin or third party.
My advice is to generally ignore the API documentation on Mozilla's L20n website with the exception of their guide to FTL, the L20n translation format.
Finally, it's worth noting that L20n depends upon the ECMAScript
Internationalization API (found in browsers under window.Intl
), which is
provided via polyfill. This module also removes bidirectional isolation
characters which are inserted by L20n, but not supported by either React Native
platform.
L20n.create(translations)
translations
is an object that maps locales to translations.
Locales are specified as two-letter ISO 639-1 codes.
Translations are specified in L20n's FTL format.
L20n.create()
returns an object that maps each translation key to a function.
The function can be invoked with a single object argument to provide variables
for substitution into the translated string.
When the function is invoked, a translation for the current locale is used; if none is available, the default locales are attempted in order. Failing that, the translation key is returned.
Example:
import L20n from 'react-native-l20n';
const l20n = L20n.create({
en: `key = The value is: {$variable}`
es: `key = El valor es: {$variable}`
});
console.log(l20n.key({variable: 'foo'));
// => "The value is: foo" if device is in English
// => "El valor es: foo" if device is in Spanish
L20.currentLocale
Get or set the current locale.
The locale is specified as a two-letter ISO 639-1 code.
The value is initialized to the locale of the device. If you wish to programmatically change it, do so before rendering your first component.
L20.defaultLocales
Get or set the default locales.
Locales are specified as two-letter ISO 639-1 codes.
These locales are attempted when a translation isn't available for the current
locale.
Defaults to ['en']
. If you wish to programmatically change it, do so before
rendering your first component.
ftl
ES6 templated string tag for FTL, the L20n translation format.
The ftl
tag is not required, but enables you to indent your translations,
which is not normally legal. It also removes newlines from piped, multi-line
translations, which emulates the whitespace-collapsing nature of HTML.
Example:
import {ftl} from 'react-native-l20n';
const translations = {
en: ftl`
firstKey = First
secondKey =
| This string spans
| multiple lines.
`,
};
console.log(translations.en);
// (The output is legal FTL.) =>
// firstKey = First
// secondKey =
// | This string spans multiple lines.
One of the creators of L20n, @stasm, has been exploring proposals for deeper integration of L20n into browser-based React. A very thorough series of proposals is under discussion on this thread.
The approach of this module is to hew as closely as possible to plain-old portable JavaScript, with some conveniences added to conform with React Native idioms. Perhaps L20n will formalize an API that requires neither DOM access or Node.js builtin modules, which would eliminate the need to vendor a modified version of the L20n framework. (This would likely involve isolating the FTL parser and runtime from the rest of L20n.)
Beyond that, there are a number of enhancements that could be added to this module to mature it into a scalable localization solution:
Handle the TODOs
listed at the top of the source.
Generalize this module for use in browser-based React or apart from any framework. This would essentially substitute for the L20n Node.js interface, which is a bit lacking.
Build tooling to collect strings from components, and support loading/bundling of translations into separate files, apart from the component definitions.
Build a runtime inspector to identify translation keys.
More than anything, I'd appreciate your feedback on what it will take for this module to become a production-grade solution for your project. Please open an issue to discuss.
FAQs
Mozilla's L20n localization framework for React Native
The npm package react-native-l20n receives a total of 1 weekly downloads. As such, react-native-l20n popularity was classified as not popular.
We found that react-native-l20n demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.