-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathPersonalization.js
More file actions
156 lines (137 loc) · 6.17 KB
/
Personalization.js
File metadata and controls
156 lines (137 loc) · 6.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import { setLocale, loadJSON, getLocale } from 'src/utilities/Intl'
// gettext related base language files
import frCa from 'src/const/language/frCa.json'
import enCa from 'src/const/language/enCa.json'
// This is a catch all for spanish. Country code optional.
import es from 'src/const/language/es.json'
// gettext related custom copy language files
import exampleFrCa from 'src/const/language/custom_copy/example_custom_copy-fr-ca.json'
import exampleEnUs from 'src/const/language/custom_copy/example_custom_copy-en-us.json'
import regionsEnUs from 'src/const/language/custom_copy/regions_custom_copy-en-us.json'
import mandtEnUs from 'src/const/language/custom_copy/mandt_custom_copy-en-us.json'
import nohoEnUs from 'src/const/language/custom_copy/noho_custom_copy-en-us.json'
// These keys match up with our /language/custom_copy/FILENAMES, to load specific client copy
const CLIENT_CUSTOM_COPY = {
[generateClientCustomCopyKey('fr-ca', 'example')]: exampleFrCa,
[generateClientCustomCopyKey('en', 'example')]: exampleEnUs,
[generateClientCustomCopyKey('en', 'regions')]: regionsEnUs,
[generateClientCustomCopyKey('en', 'mandt')]: mandtEnUs,
[generateClientCustomCopyKey('en', 'noho')]: nohoEnUs,
}
// These keys match up with our base non-generic english language files
const LOCALE_TO_STRINGS = {
'en-ca': enCa,
'fr-ca': frCa,
es,
}
/**
* Based on the locale, we load up our base language strings, if we are in english then we
* don't load a specific language file, as we fall back to our initial provided strings.
*
* If we are using a different language, we get that language file.
*
* We then check for any custom copy based on an optionally provided "custom_copy_namespace" from the client_profile.
* This is opt-in functionality, and works normally if one isnt provided.
*
* We then combine both objects to ultimately give gettext the final string object via `loadJSON()`
*
* == To add custom copy for a client you'll want to do the following:
* ==== Create a `constants/language/custom_copy/{namespace}_custom_copy-{lang}.json` file.
* ==== Add the entry to the CLIENT_CUSTOM_COPY object for each language they want to support.
* ==== Manually add the translations entry to their custom copy file (which will cause the overriding of our base strings or language specific strings)
*
* Code Example:
* # This is used if you want to replace all instances of this string
* {__('Connect your account')}
* === The argument is the actual english string
*
* # This is used when you only want to replace this string instance
* {_p('connect-disclosure', 'Connect your account')}
* === The first argument is the unique key for that specific text
* === The second argument is the actual english string
*
* == Run `npm run i18n extract`, this will create a new entry in our `messages.po` file.
* == Copy that entry into the {language}.po file (if it's in a language with an existing language file), add the translation.
* === If not, you'll just add it directly to the custom copy language file.
* == Run `npm run i18n po2json`, which will auto generate your {language}.json file.
* == Copy the line added into your custom copy language file
*
* The flow of language and personalization data is as follows:
*
* ENGLISH <- BASE_LANGAGE (determined from firefly then widget loader config) <- CUSTOM_COPY
*
* Order to determine which locale is used
* 1) Firefly HTML attribute
* 2) clientConfig via the widget loader
*
* In the future, the language and or custom copy files could easily be coming from a backend service instead of in the repo.
*/
/**
* This function sets up all of the needed gettext behavior
* This sets our locale, determines our language files along with loading the client custom copy
*
* @param {{locale: string, custom_copy_namespace: string}} options
*/
export const initGettextLocaleData = (options) => {
// Get our locale based on the way it's supplied to us
const locale = determineLocaleToUse(getLocale(), options.locale)
// Set our locale
setLocale(locale.toLowerCase())
// Pass in the client custom copy namespace, example: 'greyfield' (this will come from the client profile)
const baseStrings = getBaseLocaleStrings(locale)
const customStrings = getCustomLocaleStrings(locale, options.custom_copy_namespace)
const mergedCopy = { ...baseStrings, ...customStrings }
// Load our JSON only if we have any keys based on language and custom copy files
if (Object.keys(mergedCopy).length) {
loadJSON(mergedCopy)
}
}
/**
* Compares gettext locale with supplied reactLocale, if they differ we favor the reactLocale since that
* means it's from the widget loader configuration which should override everything else
*
* @param {string} gettextLocale
* @param {string} reactLocale
* @returns {string} locale
*/
export const determineLocaleToUse = (gettextLocale, reactLocale) => {
if (!reactLocale) {
return scrubLocale(gettextLocale)
}
const scrubbedReactLocale = scrubLocale(reactLocale)
return gettextLocale.toLowerCase() === scrubbedReactLocale ? gettextLocale : scrubbedReactLocale
}
/**
* When we support more languages, we simply add a new case
*
* @param {string} locale
* @returns {object} Either hydrated or empty
*/
export const getBaseLocaleStrings = (locale) => LOCALE_TO_STRINGS[locale.toLowerCase()] || {}
/**
* Does a look up based on the customCopyNamespace to return the clients custom copy
*
* @param {string} locale
* @param {string} customCopyNamespace
* @returns {object} Either hydrated or empty
*/
export const getCustomLocaleStrings = (locale, customCopyNamespace) => {
const customCopyKey = generateClientCustomCopyKey(locale, customCopyNamespace)
return CLIENT_CUSTOM_COPY[customCopyKey] ?? {}
}
/**
* Produces the full string for the copy look up
*
* @param {string} locale
* @param {string} customCopyNamespace
* @returns {string} ex: 'greyfield_custom_copy-en-us'
*/
function generateClientCustomCopyKey(locale, customCopyNamespace) {
return `${customCopyNamespace}_custom_copy-${locale}`.toLowerCase()
}
// prepare the locale for lookup
export const scrubLocale = (locale) => {
const lowerLocale = locale.toLowerCase()
// use react-intl's default of 'en'
return lowerLocale === 'en-us' ? 'en' : lowerLocale
}