UNPKG

3.22 kBPlain TextView Raw
1import { Locale, LocalizedString, LocalizerData } from "."
2
3/**
4 * Localizer is a function that sets up global variable "T" which is
5 * used to translate strings. Also sets up Handlebars helper with same name
6 * Function "T" maps to Localizer "localizeString" function
7 * Helper "T" maps to Localizer "localizeString" function
8 */
9export default class Localizer {
10 data: LocalizerData
11
12 /** Current locale */
13 locale: string
14
15 englishMap: { [english: string]: LocalizedString }
16
17 /** Locale defaults to "en" */
18 constructor(data: LocalizerData, locale?: string) {
19 this.T = this.T.bind(this)
20 this.data = data
21 this.locale = locale || "en"
22
23 // Index strings by English if data present
24 this.englishMap = {}
25 if (data != null) {
26 for (let str of this.data.strings) {
27 this.englishMap[str.en] = str
28 }
29 }
30 }
31
32 /** Set the current locale */
33 setLocale(locale: string): void {
34 this.locale = locale
35 }
36
37 getLocales(): Locale[] {
38 return this.data.locales
39 }
40
41 T(str: any, ...args: any[]) {
42 return this.localizeString.apply(this, arguments)
43 }
44
45 localizeString = (str: any, ...args: any[]) => {
46 // Null is just pass-through
47 if (str == null) {
48 return str
49 }
50
51 // True if object passed in as arg (react style)
52 let hasObject = false
53
54 for (let arg of args) {
55 if (arg && typeof arg === "object") {
56 hasObject = true
57 }
58 }
59
60 if (!hasObject) {
61 return this.localizePlainString(str, ...args)
62 } else {
63 // Find string, falling back to English
64 let locstr
65 const item = this.englishMap[str]
66 if (item && item[this.locale]) {
67 locstr = item[this.locale]
68 } else {
69 locstr = str
70 }
71
72 // Split and do react-style replacement where string is made into array
73 const parts = locstr.split(/(\{\d+\})/)
74
75 const output = []
76 for (let part of parts) {
77 if (part.match(/^\{\d+\}$/)) {
78 output.push(args[parseInt(part.substr(1, part.length - 2))])
79 } else {
80 output.push(part)
81 }
82 }
83
84 return output
85 }
86 }
87
88 // Localizes a plain string without React-style interpretation. Needed for handlebars as it passes extra arguments
89 localizePlainString = (str: any, ...args: any[]) => {
90 // Find string, falling back to English
91 let locstr
92 const item = this.englishMap[str]
93 if (item && item[this.locale]) {
94 locstr = item[this.locale]
95 } else {
96 locstr = str
97 }
98
99 // Fill in arguments
100 for (let i = 0, end = args.length, asc = 0 <= end; asc ? i < end : i > end; asc ? i++ : i--) {
101 locstr = locstr.replace("{" + i + "}", args[i])
102 }
103 return locstr
104 }
105
106 /** Determines if a string is localized */
107 isLocalized(str: string): boolean {
108 return str != null && this.englishMap[str] != null && this.englishMap[str][this.locale] != null
109 }
110
111 // Makes this localizer global. handlebars is instance to register
112 // helper on, null for none
113 makeGlobal(handlebars: any) {
114 (global as any).T = this.localizeString;
115 (global as any).T.localizer = this;
116 if (handlebars != null) {
117 return handlebars.registerHelper("T", this.localizePlainString)
118 }
119 }
120}