@shopify/react-i18n
Advanced tools
Comparing version 0.0.2 to 0.0.3
@@ -1,4 +0,4 @@ | ||
import { TranslationDictionary } from './types'; | ||
import { TranslationDictionary, MaybePromise } from './types'; | ||
export interface TranslationGetter { | ||
(locale: string): TranslationDictionary | Promise<TranslationDictionary | undefined> | undefined; | ||
(locale: string): MaybePromise<TranslationDictionary | undefined>; | ||
} | ||
@@ -5,0 +5,0 @@ export interface Options { |
import * as React from 'react'; | ||
import I18n from './i18n'; | ||
import { TranslationDictionary } from './types'; | ||
import { TranslationDictionary, MaybePromise } from './types'; | ||
export interface WithI18nOptions { | ||
@@ -8,3 +8,3 @@ id?: string; | ||
renderWhileLoading?: boolean; | ||
translations?(locale: string): TranslationDictionary | Promise<TranslationDictionary> | undefined; | ||
translations?(locale: string): MaybePromise<TranslationDictionary | undefined>; | ||
} | ||
@@ -11,0 +11,0 @@ export interface WithI18nProps { |
"use strict"; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
var extendStatics = function (d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
} | ||
return function (d, b) { | ||
@@ -12,9 +15,12 @@ extendStatics(d, b); | ||
})(); | ||
var __assign = (this && this.__assign) || Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
@@ -21,0 +27,0 @@ var __importStar = (this && this.__importStar) || function (mod) { |
"use strict"; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
var extendStatics = function (d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
} | ||
return function (d, b) { | ||
@@ -7,0 +10,0 @@ extendStatics(d, b); |
"use strict"; | ||
var __assign = (this && this.__assign) || Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
@@ -93,5 +96,12 @@ var __rest = (this && this.__rest) || function (s, e) { | ||
I18n.prototype.translate = function (id, optionsOrReplacements, replacements) { | ||
var normalizedOptions = replacements == null | ||
? optionsOrReplacements || {} | ||
: __assign({}, optionsOrReplacements, { replacements: replacements }); | ||
var normalizedOptions; | ||
if (optionsOrReplacements == null) { | ||
normalizedOptions = {}; | ||
} | ||
else if (isTranslateOptions(optionsOrReplacements)) { | ||
normalizedOptions = __assign({}, optionsOrReplacements, { replacements: replacements }); | ||
} | ||
else { | ||
normalizedOptions = { replacements: optionsOrReplacements }; | ||
} | ||
return utilities_1.translate(id, normalizedOptions, this.translations, this.locale); | ||
@@ -118,1 +128,4 @@ }; | ||
exports.default = I18n; | ||
function isTranslateOptions(object) { | ||
return 'scope' in object; | ||
} |
@@ -278,4 +278,4 @@ "use strict"; | ||
} | ||
function isPromise(possiblePromise) { | ||
return possiblePromise != null && possiblePromise.then != null; | ||
function isPromise(maybePromise) { | ||
return maybePromise != null && maybePromise.then != null; | ||
} | ||
@@ -282,0 +282,0 @@ function filterUndefined(array) { |
"use strict"; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
var extendStatics = function (d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
} | ||
return function (d, b) { | ||
@@ -7,0 +10,0 @@ extendStatics(d, b); |
@@ -20,1 +20,2 @@ /// <reference types="react" /> | ||
} | ||
export declare type MaybePromise<T> = T | Promise<T>; |
{ | ||
"name": "@shopify/react-i18n", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"license": "MIT", | ||
@@ -9,3 +9,3 @@ "description": "i18n utilities for React handling translations, formatting, and more.", | ||
"scripts": { | ||
"build": "tsc", | ||
"build": "tsc --p tsconfig.build.json", | ||
"prepublishOnly": "yarn run build", | ||
@@ -29,3 +29,3 @@ "test": "jest --config ./config/jest/config.json" | ||
"intl-pluralrules": "^0.2.1", | ||
"typescript": "~2.9.2" | ||
"typescript": "~3.0.1" | ||
}, | ||
@@ -32,0 +32,0 @@ "dependencies": { |
@@ -125,4 +125,3 @@ # `@shopify/react-i18n` | ||
"action": "Back", | ||
"content": | ||
"The page you were looking for could not be found. Please check the web address for errors and try again." | ||
"content": "The page you were looking for could not be found. Please check the web address for errors and try again." | ||
} | ||
@@ -228,1 +227,14 @@ } | ||
``` | ||
## FAQ | ||
### Why another i18n library? Why not just use <[react-intl](https://github.com/yahoo/react-intl) | [react-i18next](https://github.com/i18next/react-i18next)> etc? | ||
These libraries are excellent, and we may well use parts of them under the hood for this project. However, we wanted to add a Shopify-specific layer that cleanly exposes some features we feel are non-negotiable: | ||
- Per-component management of translations, to avoid the ever-growing translation files that hurt our largest apps. | ||
- Asynchronous loading of translation files, so that we can scale the number of supported languages without increasing bundle sizes. | ||
- An API for translations that feels consistent with Rails’ default i18n utilities. | ||
- Exposing currency and datetime formatting utilities that automatically follow the [Polaris conventions](https://polaris.shopify.com/content/grammar-and-mechanics#section-dates-numbers-and-addresses). | ||
Additional details on why we built our own package, and on specifics of parts of this package’s API, are available in the [original proposal](https://github.com/Shopify/web-foundation/pull/3). |
@@ -1,9 +0,6 @@ | ||
import {TranslationDictionary} from './types'; | ||
import {TranslationDictionary, MaybePromise} from './types'; | ||
import {noop} from './utilities'; | ||
export interface TranslationGetter { | ||
(locale: string): | ||
| TranslationDictionary | ||
| Promise<TranslationDictionary | undefined> | ||
| undefined; | ||
(locale: string): MaybePromise<TranslationDictionary | undefined>; | ||
} | ||
@@ -10,0 +7,0 @@ |
@@ -106,7 +106,14 @@ import { | ||
): any { | ||
const normalizedOptions = | ||
replacements == null | ||
? optionsOrReplacements || {} | ||
: {...optionsOrReplacements, replacements}; | ||
let normalizedOptions: RootTranslateOptions< | ||
PrimitiveReplacementDictionary | ComplexReplacementDictionary | ||
>; | ||
if (optionsOrReplacements == null) { | ||
normalizedOptions = {}; | ||
} else if (isTranslateOptions(optionsOrReplacements)) { | ||
normalizedOptions = {...optionsOrReplacements, replacements}; | ||
} else { | ||
normalizedOptions = {replacements: optionsOrReplacements}; | ||
} | ||
return translate(id, normalizedOptions, this.translations, this.locale); | ||
@@ -150,1 +157,10 @@ } | ||
} | ||
function isTranslateOptions( | ||
object: | ||
| TranslateOptions | ||
| PrimitiveReplacementDictionary | ||
| ComplexReplacementDictionary, | ||
): object is TranslateOptions { | ||
return 'scope' in object; | ||
} |
@@ -1,2 +0,2 @@ | ||
import {I18nDetails, TranslationDictionary} from './types'; | ||
import {I18nDetails, TranslationDictionary, MaybePromise} from './types'; | ||
import Connection from './connection'; | ||
@@ -27,5 +27,3 @@ | ||
string, | ||
| TranslationDictionary | ||
| Promise<TranslationDictionary | undefined> | ||
| undefined | ||
MaybePromise<TranslationDictionary | undefined> | ||
>; | ||
@@ -212,5 +210,5 @@ | ||
function isPromise<T>( | ||
possiblePromise: T | Promise<T>, | ||
): possiblePromise is Promise<T> { | ||
return possiblePromise != null && (possiblePromise as any).then != null; | ||
maybePromise: MaybePromise<T>, | ||
): maybePromise is Promise<T> { | ||
return maybePromise != null && (maybePromise as any).then != null; | ||
} | ||
@@ -217,0 +215,0 @@ |
@@ -145,2 +145,52 @@ import './matchers'; | ||
}); | ||
it('calls the translate() utility when no scope is provided', () => { | ||
const mockResult = 'translated string'; | ||
const replacements = {name: 'Chris'}; | ||
translate.mockReturnValue(mockResult); | ||
const i18n = new I18n(defaultTranslations, defaultDetails); | ||
const result = i18n.translate('hello', replacements); | ||
expect(result).toBe(mockResult); | ||
expect(translate).toHaveBeenCalledWith( | ||
'hello', | ||
{replacements}, | ||
defaultTranslations, | ||
i18n.locale, | ||
); | ||
}); | ||
it('calls the translate() utility when no replacements are provided', () => { | ||
const mockResult = 'translated string'; | ||
const scope = {scope: 'goodbye'}; | ||
translate.mockReturnValue(mockResult); | ||
const i18n = new I18n(defaultTranslations, defaultDetails); | ||
const result = i18n.translate('hello', scope); | ||
expect(result).toBe(mockResult); | ||
expect(translate).toHaveBeenCalledWith( | ||
'hello', | ||
{...scope}, | ||
defaultTranslations, | ||
i18n.locale, | ||
); | ||
}); | ||
it('calls the translate() utility when no replacements or scope are provided', () => { | ||
const mockResult = 'translated string'; | ||
translate.mockReturnValue(mockResult); | ||
const i18n = new I18n(defaultTranslations, defaultDetails); | ||
const result = i18n.translate('hello'); | ||
expect(result).toBe(mockResult); | ||
expect(translate).toHaveBeenCalledWith( | ||
'hello', | ||
{}, | ||
defaultTranslations, | ||
i18n.locale, | ||
); | ||
}); | ||
}); | ||
@@ -147,0 +197,0 @@ |
@@ -23,1 +23,3 @@ export enum LanguageDirection { | ||
} | ||
export type MaybePromise<T> = T | Promise<T>; |
Sorry, the diff of this file is not supported yet
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
2870
239
116997
40
1