-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit bdce51a
Showing
16 changed files
with
694 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"presets": ["es2015", "react"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
lib |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
language: node_js | ||
node_js: | ||
- 4.6.2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
ISC License | ||
|
||
Copyright (c) 2017, Darren Lucas | ||
|
||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted, provided that the above | ||
copyright notice and this permission notice appear in all copies. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
react-g11n | ||
========== | ||
|
||
An internationalisation and localization library for React. | ||
|
||
|
||
Installation | ||
------------ | ||
|
||
npm install react-g11n | ||
|
||
|
||
Usage | ||
----- | ||
|
||
The provider pattern is used to wrap your component and provide a translator | ||
object to child components. Wrap your component in a Localizer as follows: | ||
|
||
|
||
import { render } from "react-dom" | ||
import { Localizer } from "react-g11n" | ||
|
||
import App from "app" | ||
|
||
render( | ||
<Localizer locale="cy"> | ||
<App /> | ||
</Localizer> | ||
} | ||
|
||
|
||
From within a child component you can gain access to a translator property as | ||
follows: | ||
|
||
import React, { PropTypes} from "react" | ||
import { localize } from "react-g11n" | ||
|
||
class MyComponent extends React.Component { | ||
|
||
render() { | ||
const { translator } = this.props | ||
|
||
return ( | ||
<h1>{translator.gettext('Hello world!')}</h1> | ||
) | ||
|
||
} | ||
|
||
MyComponent.propTypes = { | ||
translator: PropTypes.object.isRequired | ||
} | ||
|
||
export default localize(MyComponent) | ||
|
||
|
||
The translate object exposes the a Gettext object with common gettext functions | ||
|
||
|
||
Working with gettext translation files | ||
-------------------------------------- | ||
|
||
GNU gettext is an internationalization and localization system commonly used on | ||
Unix like operating systems. | ||
|
||
Three types of files are used in the GNU gettext translation framework: | ||
|
||
* .pot (Portable Object Template) files | ||
|
||
A .pot file is created by a program which searches through a projects source code | ||
and picks out every message identifier passed to gettext translation functions. | ||
The list of message identifiers is placed into a .pot file which serves as a | ||
template for creating .po files. | ||
|
||
* .po (Portable Object) files | ||
|
||
A .po file is derived from the template and fills out the translations. | ||
|
||
* .mo (Machine Object) files | ||
|
||
A .po file is compiled into a binary .mo file optimized for reading by a machine. | ||
|
||
|
||
### Extracting messages | ||
|
||
To extract messages from javascript files use jsxgettext which can be installed | ||
from npm: | ||
|
||
npm install jsxgettext --save-dev | ||
|
||
|
||
This will install a command called jsxgettext which can be used to scan javascript | ||
code for calls to gettext and extract translations into a portable object template: | ||
|
||
mkdir -p src/locale | ||
node_modules/.bin/jsxgettext src/**/*.js -o src/locale/messages.pot | ||
|
||
This will output a .pot file to src/locale/messages.pot | ||
|
||
|
||
### Initializing a message catalog file | ||
|
||
Once messages have been extracted into a .pot file this can be used to generate a | ||
.po file. A .po file contains translations for a set of messages for a particular | ||
locale. The Gettext msginit command can be used to initialize a .po file: | ||
|
||
cd src/locale | ||
mkdir -p cy/LC_MESSAGES | ||
msginit -l cy -o cy/LC_MESSAGES/messages.po | ||
|
||
This will create a new message catalog .po file which can then be edited by a human | ||
translator using a tool such as Poedit. | ||
|
||
|
||
### Updating a message catalog file | ||
|
||
As more translation strings are added, or as existing strings are changed it will be | ||
neccessary to update existing .po files so that new and changed messages can be | ||
translated. | ||
|
||
First regenerate the .pot file as per the Extracting messages section and then use | ||
the msgmerge command from Gettext. | ||
|
||
cd src/locale | ||
msgmerge --update cy/LC_MESSAGES/messages.po messages.pot | ||
|
||
|
||
### Compiling a message catalog file | ||
|
||
To convert translation files into a machine readable binary file use the Gettext | ||
msgfmt command to convert .po files into .mo files. | ||
|
||
cd src/locale | ||
msgfmt cy/LC_MESSAGES/messages.po -o cy/LC_MESSAGES/messages.mo | ||
|
||
|
||
### Automating with Make | ||
|
||
To make the above commands easier, the can be codified into Makefile targets to | ||
provide the following phony targets: | ||
|
||
* extract-messages | ||
* update-catalog | ||
* compile-catalog | ||
|
||
An example Makefile would be: | ||
|
||
SRC_DIR = src/ | ||
POT_FILE = $(SRC_DIR)/locale/messages.pot | ||
PO_FILES := $(shell find $(SRC_DIR) -type f -name '*.po') | ||
MO_FILES := $(patsubst $(SRC_DIR)/%.po,$(SRC_DIR)/%.mo,$(PO_FILES)) | ||
|
||
JSXGETTEXT_CMD = node_modules/.bin/jsxgettext | ||
|
||
.PHONY: extract-messages | ||
extract-messages: ## Extract translations from source code | ||
$(JSXGETTEXT_CMD) $(SRC_DIR)/**/*.js -o $(POT_FILE) | ||
|
||
.PHONY: update-catalog | ||
update-catalog: $(PO_FILES) ## Update messages catalogs for all locales | ||
|
||
$(PO_FILES): $(POT_FILE) | ||
msgmerge --previous $@ $? -o $@ | ||
|
||
.PHONY: compile-catalog | ||
compile-catalog: $(MO_FILES) ## Compile messages catalogs for all locales | ||
|
||
$(MO_FILES): $(SRC_DIR)/%.mo: $(SRC_DIR)/%.po | ||
mkdir -p $(@D) | ||
msgfmt $< -o $@ | ||
|
||
|
||
A translation workflow would then be: | ||
|
||
make extract-messages | ||
make update-catalog | ||
|
||
Once translations of the generate .po files has taken place the .mo files can | ||
be compiled with: | ||
|
||
make compile-catalog | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{ | ||
"name": "react-g11n", | ||
"version": "0.1.0", | ||
"description": "Globalization for react components using gettext", | ||
"main": "./lib/index.js", | ||
"files": [ | ||
"README.md", | ||
"LICENSE", | ||
"lib" | ||
], | ||
"scripts": { | ||
"start": "babel src --out-dir lib", | ||
"test": "jest" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/darrenlucas/react-g11n.git" | ||
}, | ||
"author": "Darren Lucas", | ||
"license": "ISC", | ||
"bugs": { | ||
"url": "https://github.com/darrenlucas/react-g11n/issues" | ||
}, | ||
"homepage": "https://github.com/darrenlucas/react-g11n#readme", | ||
"dependencies": { | ||
"gettext-parser": "^1.2.2" | ||
}, | ||
"devDependencies": { | ||
"babel-cli": "^6.18.0", | ||
"babel-jest": "^18.0.0", | ||
"babel-preset-es2015": "^6.18.0", | ||
"babel-preset-react": "^6.16.0", | ||
"jest": "^18.1.0", | ||
"react": "^15.4.2", | ||
"react-test-renderer": "^15.4.2" | ||
}, | ||
"jest": { | ||
"testPathDirs": [ | ||
"./test" | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
let GettextMixin = (superclass) => class extends superclass { | ||
|
||
_translate(message) { | ||
if (super.translate) { | ||
return super.translate.apply(this, arguments); | ||
} | ||
return message; | ||
} | ||
|
||
_pluralize(singular, plural, number) { | ||
if (super.pluralize) { | ||
return super.pluralize.apply(this, arguments); | ||
} | ||
return this._translate((number != 1) ? singular : plural); | ||
} | ||
|
||
/** | ||
* Translate a string using the current domain. | ||
* | ||
* @param {String} message String to be translated | ||
* @return {String} translated string | ||
*/ | ||
gettext(message) { | ||
return this._translate(message); | ||
} | ||
|
||
/** | ||
* Translate a string using the specified domain. | ||
* | ||
* @param {String} domain The domain to use | ||
* @param {String} message String to be translated | ||
* @return {String} translated string | ||
*/ | ||
dgettext(domain, message) { | ||
return this._translate(message, { domain: domain }); | ||
} | ||
|
||
/** | ||
* Translate a string taking into consideration plural forms. | ||
* Some languages have more than two plural forms. | ||
* | ||
* @param {String} singular Singular form string to be translated | ||
* @param {String} plural Plural form string to be translated | ||
* @param {Number} number Number for the plural | ||
* @return {String} translated string | ||
*/ | ||
ngettext(singular, plural, number) { | ||
return this._pluralize(singular, plural, number); | ||
} | ||
|
||
/** | ||
* Translate a string taking into consideration plural forms using | ||
* the specified domain | ||
* | ||
* @param {String} domain The domain to use | ||
* @param {String} singular Singular form string to be translated | ||
* @param {String} plural Plural form string to be translated | ||
* @param {Number} number Number for the plural | ||
* @return {String} translated string | ||
*/ | ||
dngettext(domain, singular, plural, number) { | ||
return this._pluralize(singular, plural, number, { domain: domain }); | ||
} | ||
|
||
/** | ||
* Translate a string for the specified context using the current domain. | ||
* | ||
* @param {String} context Translation context | ||
* @param {String} message String to be translated | ||
* @return {String} translated string | ||
*/ | ||
pgettext(context, message) { | ||
return this._translate(message, { context: context }); | ||
} | ||
|
||
/** | ||
* Translate a string using the specified domain and context | ||
* | ||
* @param {String} domain The domain to use | ||
* @param {String} context Translation context | ||
* @param {String} message String to be translated | ||
* @return {String} translated string | ||
*/ | ||
dpgettext(domain, context, message) { | ||
return this._translate(message, { domain: domain, context: context }); | ||
} | ||
|
||
/** | ||
* Translate a string for the specified context taking into consideration | ||
* plural forms. | ||
* | ||
* @param {String} context Translation context | ||
* @param {String} singular Singular form string to be translated | ||
* @param {String} plural Plural form string to be translated | ||
* @param {Number} number Number for the plural | ||
* @return {String} translated string | ||
*/ | ||
npgettext(context, singular, plural, number) { | ||
return this._pluralize(singular, plural, number, { context: context }); | ||
} | ||
|
||
/** | ||
* Translate a string for the specified domain and context taking into | ||
* consideration plural forms. | ||
* | ||
* @param {String} domain The domain to use | ||
* @param {String} context Translation context | ||
* @param {String} singular Singular form string to be translated | ||
* @param {String} plural Plural form string to be translated | ||
* @param {Number} number Number for the plural | ||
* @return {String} translated string | ||
*/ | ||
dnpgettext(domain, context, singular, plural, number) { | ||
return this._pluralize(singular, plural, number, { domain: domain, context: context }); | ||
} | ||
|
||
} | ||
|
||
export default GettextMixin; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import localize from './localize'; | ||
import Localizer from './localizer'; | ||
|
||
export { localize as localize }; | ||
export default Localizer; |
Oops, something went wrong.