next-multilingual
Advanced tools
Comparing version 0.1.2 to 0.1.3
@@ -39,2 +39,4 @@ import { KeyValueObject } from './properties'; | ||
private message; | ||
/** The IntlMessageFormat objet, if required. */ | ||
private intlMessageFormat; | ||
/** | ||
@@ -64,2 +66,4 @@ * Create an object used to format localized messages of a local scope. | ||
private messages; | ||
/** The current locale from Next.js. */ | ||
readonly locale: string; | ||
/** The source (the file calling `useMessages`) file path. */ | ||
@@ -73,6 +77,7 @@ readonly sourceFilePath: string; | ||
* @param keyValueObject - The "key/value" object coming directly from a `.properties` file. | ||
* @param locale - The current locale from Next.js. | ||
* @param sourceFilePath - The file path of the source file associated with the messages. | ||
* @param messagesFilePath - The file path of the messages. | ||
*/ | ||
constructor(keyValueObject: KeyValueObject, sourceFilePath: string, messagesFilePath: string); | ||
constructor(keyValueObject: KeyValueObject, locale: string, sourceFilePath: string, messagesFilePath: string); | ||
/** | ||
@@ -79,0 +84,0 @@ * Format a message identified by a key in a local scope. |
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -8,2 +11,3 @@ exports.useMessages = exports.Messages = exports.Message = exports.getSourceFilePath = exports.getMessagesFilePath = exports.urlSegmentKeyId = exports.keySegmentRegExp = void 0; | ||
const __2 = require(".."); | ||
const intl_messageformat_1 = __importDefault(require("intl-messageformat")); | ||
/** This is the regular expression to validate message key segments. */ | ||
@@ -49,2 +53,4 @@ exports.keySegmentRegExp = /^[a-z\d]{3,50}$/i; | ||
message; | ||
/** The IntlMessageFormat objet, if required. */ | ||
intlMessageFormat; | ||
/** | ||
@@ -72,3 +78,6 @@ * Create an object used to format localized messages of a local scope. | ||
if (values) { | ||
// todo: implement value | ||
this.intlMessageFormat = this.intlMessageFormat | ||
? this.intlMessageFormat | ||
: new intl_messageformat_1.default(this.message, this.parent.locale); | ||
return String(this.intlMessageFormat.format(values)); | ||
} | ||
@@ -85,2 +94,4 @@ return this.message; | ||
messages = []; | ||
/** The current locale from Next.js. */ | ||
locale; | ||
/** The source (the file calling `useMessages`) file path. */ | ||
@@ -94,6 +105,7 @@ sourceFilePath; | ||
* @param keyValueObject - The "key/value" object coming directly from a `.properties` file. | ||
* @param locale - The current locale from Next.js. | ||
* @param sourceFilePath - The file path of the source file associated with the messages. | ||
* @param messagesFilePath - The file path of the messages. | ||
*/ | ||
constructor(keyValueObject, sourceFilePath, messagesFilePath) { | ||
constructor(keyValueObject, locale, sourceFilePath, messagesFilePath) { | ||
if (keyValueObject) { | ||
@@ -104,2 +116,3 @@ Object.keys(keyValueObject).forEach((key) => { | ||
} | ||
this.locale = (0, __1.normalizeLocale)(locale); | ||
this.sourceFilePath = sourceFilePath; | ||
@@ -117,4 +130,5 @@ this.messagesFilePath = messagesFilePath; | ||
format(key, values) { | ||
if (this.messages === undefined) { | ||
if (!this.messages.length) { | ||
// No need to log the error since it was caught when calling `useMessage()`. | ||
__2.log.warn('uhuh 0 length'); | ||
return ''; | ||
@@ -156,6 +170,6 @@ } | ||
if (!babelifiedMessages.keyValueObjectCollection[locale]) { | ||
__2.log.warn(`unable to use \`useMessages()\` in \`${babelifiedMessages.sourceFilePath}\` because the messages file was not found at \`${messagesFilePath}\``); | ||
__2.log.warn(`unable to use \`useMessages()\` in \`${babelifiedMessages.sourceFilePath}\` because no messagess could be found at \`${messagesFilePath}\``); | ||
} | ||
return new Messages(babelifiedMessages.keyValueObjectCollection[locale], sourceFilePath, messagesFilePath); | ||
return new Messages(babelifiedMessages.keyValueObjectCollection[locale], locale, sourceFilePath, messagesFilePath); | ||
} | ||
exports.useMessages = useMessages; |
{ | ||
"name": "next-multilingual", | ||
"description": "An opinionated end-to-end multilingual solution for Next.js.", | ||
"version": "0.1.2", | ||
"version": "0.1.3", | ||
"license": "MIT", | ||
@@ -49,3 +49,5 @@ "main": "lib/index.js", | ||
"globalization", | ||
"g11n" | ||
"g11n", | ||
"ICU", | ||
"MessageFormat" | ||
], | ||
@@ -78,19 +80,20 @@ "author": "Avansai (https://avansai.com)", | ||
"dot-properties": "^1.0.1", | ||
"intl-messageformat": "^9.9.1", | ||
"nookies": "^2.5.2", | ||
"resolve-accept-language": "^1.0.31" | ||
"resolve-accept-language": "^1.0.32" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.15.0", | ||
"@babel/core": "^7.15.5", | ||
"@release-it/conventional-changelog": "^3.3.0", | ||
"@types/babel__core": "^7.1.15", | ||
"@types/node": "^16.7.4", | ||
"@types/react": "^17.0.19", | ||
"@types/node": "^16.7.10", | ||
"@types/react": "^17.0.20", | ||
"@types/react-dom": "^17.0.9", | ||
"@typescript-eslint/eslint-plugin": "^4.29.3", | ||
"@typescript-eslint/parser": "^4.29.3", | ||
"@typescript-eslint/eslint-plugin": "^4.30.0", | ||
"@typescript-eslint/parser": "^4.30.0", | ||
"dotenv-cli": "^4.0.0", | ||
"eslint": "^7.32.0", | ||
"eslint-config-next": "^11.1.0", | ||
"eslint-config-next": "^11.1.2", | ||
"eslint-config-prettier": "^8.3.0", | ||
"eslint-plugin-prettier": "^3.4.1", | ||
"eslint-plugin-prettier": "^4.0.0", | ||
"eslint-plugin-react-hooks": "^4.2.0", | ||
@@ -100,3 +103,3 @@ "express": "^4.17.1", | ||
"lint-staged": "^11.1.2", | ||
"next": "^11.1.0", | ||
"next": "^11.1.3-canary.7", | ||
"npm-watch": "^0.11.0", | ||
@@ -103,0 +106,0 @@ "prettier": "^2.3.2", |
@@ -339,3 +339,3 @@ # ![next-multilingual](./assets/next-multilingual-banner.svg) | ||
```ini | ||
```properties | ||
# Homepage title (will not be used as a URL segment) | ||
@@ -368,3 +368,3 @@ exampleApp.homepage.pageTitle = Homepage | ||
```ini | ||
```properties | ||
exampleApp.aboutUsPage.pageTitle = About Us | ||
@@ -428,3 +428,3 @@ exampleApp.aboutUsPage.details = This is just some english boilerplate text. | ||
```ini | ||
```properties | ||
# This is the message in the footer at the bottom of pages | ||
@@ -454,3 +454,3 @@ exampleApp.footerComponent.footerMessage = © Footer | ||
```ini | ||
```properties | ||
exampleApp.fruits.banana = Banana | ||
@@ -494,2 +494,36 @@ exampleApp.fruits.apple = Apple | ||
### Message Variables | ||
Using variables in messages is a critical functionality as not all messages contain static text. `next-multilingual` supports the [ICU MessageFormat](https://unicode-org.github.io/icu/userguide/format_parse/messages/) syntax out of the box which means that you can use the following message: | ||
```properties | ||
exampleApp.homepage.welcome = Hello, {firstName} {lastName}! | ||
``` | ||
And inject back the values using: | ||
```ts | ||
messages.format('welcome', { firstName: 'John', lastName: 'Doe' }) | ||
``` | ||
If you do not provide the values of your variables when formatting the message, it will simply output the message as static text. | ||
#### Plurals | ||
One of the main benefit of ICU MessageFormat is to use Unicode's tools and standards to enable applications to sound fluent in most languages. A lot of engineers might believe that by having 2 messages, one for singular and one for plural is enough to stay fluent in all languages. In fact, Unicode documented the [plural rules](https://unicode-org.github.io/cldr-staging/charts/latest/supplemental/language_plural_rules.html) of over 200 languages and some languages like Arabic an have up to 6 plural forms. | ||
To ensure that your sentence will stay fluent in all languages, you can use the following message: | ||
```properties | ||
exampleApp.homepage.mfPlural = {count, plural, =0 {No candy left.} one {Got # candy left.} other {Got # candies left.}} | ||
``` | ||
And the correct plural form will be picked, using the corret plural categories defined by Unicode: | ||
```ts | ||
messages.format('mfPlural', { count }) | ||
``` | ||
There is a lot to learn on this topic. Make sure to read the Unicode documentation and [try the syntax yourself](https://format-message.github.io/icu-message-format-for-translators/editor.html) to get more familiar with this under-hyped i18n capability. | ||
### Search Engine Optimization | ||
@@ -555,3 +589,3 @@ | ||
```ini | ||
```properties | ||
exampleApp.pageNotFoundError.pageTitle = 404 - Page Not Found | ||
@@ -558,0 +592,0 @@ exampleApp.pageNotFoundError.goBack = Go back home |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
129591
2067
606
5
+ Addedintl-messageformat@^9.9.1
+ Added@formatjs/ecma402-abstract@1.11.4(transitive)
+ Added@formatjs/fast-memoize@1.2.1(transitive)
+ Added@formatjs/icu-messageformat-parser@2.1.0(transitive)
+ Added@formatjs/icu-skeleton-parser@1.3.6(transitive)
+ Added@formatjs/intl-localematcher@0.2.25(transitive)
+ Addedintl-messageformat@9.13.0(transitive)
+ Addedtslib@2.8.1(transitive)