Skip to content

Commit c44a4df

Browse files
fix: setCurrent (#24)
* fix: setCurrent pulling double duty and loading languages when it shouldnt * chore: refactor, improve test coverage * Update src/mi18n.js remove redundant applyLanguage Co-authored-by: Copilot <[email protected]> * Update src/mi18n.test.js Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
1 parent 18bc3fd commit c44a4df

File tree

2 files changed

+277
-45
lines changed

2 files changed

+277
-45
lines changed

src/mi18n.js

Lines changed: 51 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ export class I18N {
3232
*/
3333
processConfig(options) {
3434
const { location, ...restOptions } = { ...DEFAULT_CONFIG, ...options }
35-
const parsedLocation = location.replace(/\/?$/, '/')
35+
// Ensure location ends with a slash
36+
const parsedLocation = location.endsWith('/') ? location : `${location}/`
3637
this.config = { location: parsedLocation, ...restOptions }
3738
const { override, preloaded = {} } = this.config
3839
const allLangs = Object.entries(this.langs).concat(Object.entries(override || preloaded))
@@ -61,7 +62,8 @@ export class I18N {
6162
addLanguage(locale, lang = {}) {
6263
lang = typeof lang === 'string' ? I18N.processFile(lang) : lang
6364
this.applyLanguage(locale, lang)
64-
this.config.langs.push('locale')
65+
this.loaded.push(locale)
66+
this.config.langs.push(locale)
6567
}
6668

6769
/**
@@ -92,14 +94,14 @@ export class I18N {
9294
*/
9395
makeSafe(str) {
9496
const mapObj = {
95-
'{': '\\{',
96-
'}': '\\}',
97-
'|': '\\|',
97+
'{': String.raw`\{`,
98+
'}': String.raw`\}`,
99+
'|': String.raw`\|`,
98100
}
99101

100-
str = str.replace(/[{}|]/g, matched => mapObj[matched])
102+
const escapedStr = str.replaceAll(/[{}|]/g, matched => mapObj[matched])
101103

102-
return new RegExp(str, 'g')
104+
return new RegExp(escapedStr, 'g')
103105
}
104106

105107
/**
@@ -121,23 +123,32 @@ export class I18N {
121123
* @return {String} updated string translation
122124
*/
123125
get(key, args) {
124-
const _this = this
125126
let value = this.getValue(key)
126127
if (!value) {
127128
return
128129
}
129130

131+
// No replacement needed if no args provided
132+
if (!args) {
133+
return value
134+
}
135+
130136
const tokens = value.match(/\{[^}]+?\}/g)
131137

132-
if (args && tokens) {
133-
if ('object' === typeof args) {
134-
for (const token of tokens) {
135-
const key = token.substring(1, token.length - 1)
136-
value = value.replace(_this.makeSafe(token), args[key] || '')
137-
}
138-
} else {
139-
value = value.replace(/\{[^}]+?\}/g, args)
138+
// No tokens to replace
139+
if (!tokens) {
140+
return value
141+
}
142+
143+
// Object args: replace each token with corresponding key
144+
if (typeof args === 'object') {
145+
for (const token of tokens) {
146+
const tokenKey = token.slice(1, -1)
147+
value = value.replace(this.makeSafe(token), args[tokenKey] ?? '')
140148
}
149+
} else {
150+
// Primitive args: replace all tokens with same value
151+
value = value.replaceAll(/\{[^}]+?\}/g, args)
141152
}
142153

143154
return value
@@ -149,7 +160,7 @@ export class I18N {
149160
* @return {Object} processed language
150161
*/
151162
static processFile(response) {
152-
return I18N.fromFile(response.replace(/\n\n/g, '\n'))
163+
return I18N.fromFile(response.replaceAll('\n\n', '\n'))
153164
}
154165

155166
/**
@@ -165,7 +176,7 @@ export class I18N {
165176
const regex = /^(.+?) *?= *?([^\n]+)/
166177
matches = regex.exec(lines[i])
167178
if (matches) {
168-
lang[matches[1]] = matches[2].replace(/(^\s+|\s+$)/g, '')
179+
lang[matches[1]] = matches[2].trim()
169180
}
170181
}
171182

@@ -178,28 +189,24 @@ export class I18N {
178189
* @param {Boolean} useCache
179190
* @return {Promise} resolves response
180191
*/
181-
loadLang(locale, useCache = true) {
182-
const _this = this
183-
return new Promise(function (resolve, reject) {
184-
if (_this.loaded.indexOf(locale) !== -1 && useCache) {
185-
_this.applyLanguage(_this.langs[locale])
186-
return resolve(_this.langs[locale])
187-
} else {
188-
const langFile = [_this.config.location, locale, _this.config.extension].join('')
189-
return fetchData(langFile)
190-
.then(lang => {
191-
const processedFile = I18N.processFile(lang)
192-
_this.applyLanguage(locale, processedFile)
193-
_this.loaded.push(locale)
194-
return resolve(_this.langs[locale])
195-
})
196-
.catch(err => {
197-
console.error(err)
198-
const lang = _this.applyLanguage(locale)
199-
resolve(lang)
200-
})
201-
}
202-
})
192+
async loadLang(locale, useCache = true) {
193+
// Return cached language if already loaded
194+
if (this.loaded.includes(locale) && useCache) {
195+
return this.langs[locale]
196+
}
197+
// Fetch and process language file
198+
const langFile = `${this.config.location}${locale}${this.config.extension}`
199+
200+
try {
201+
const lang = await fetchData(langFile)
202+
const processedFile = I18N.processFile(lang)
203+
this.applyLanguage(locale, processedFile)
204+
this.loaded.push(locale)
205+
return this.langs[locale]
206+
} catch (err) {
207+
console.error(err)
208+
return this.applyLanguage(locale)
209+
}
203210
}
204211

205212
/**
@@ -229,7 +236,10 @@ export class I18N {
229236
* @return {Promise} language
230237
*/
231238
async setCurrent(locale = 'en-US') {
232-
await this.loadLang(locale)
239+
if (!this.loaded.includes(locale)) {
240+
await this.loadLang(locale)
241+
}
242+
233243
this.locale = locale
234244
this.current = this.langs[locale]
235245

0 commit comments

Comments
 (0)