Skip to content
Open
6 changes: 2 additions & 4 deletions src/core/KeyDetector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,9 @@ export class KeyDetector {
return keyRange?.key
}

static getScopedKey(document: TextDocument, position: Position)
{
static getScopedKey(document: TextDocument, position: Position) {
const scopes = Global.enabledFrameworks.flatMap(f => f.getScopeRange(document) || [])
if (scopes.length > 0)
{
if (scopes.length > 0) {
const offset = document.offsetAt(position)
return scopes.filter(s => s.start < offset && offset < s.end).map(s => s.namespace).join('.')
}
Expand Down
4 changes: 2 additions & 2 deletions src/core/Translator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export class Translator {
catch (err) {
// eslint-disable-next-line no-console
console.error(err)
failedJobs.push([job, err])
failedJobs.push([job, err as Error])
}
finished += 1
progress.report({ increment, message })
Expand Down Expand Up @@ -318,7 +318,7 @@ export class Translator {
break
}
catch (e) {
errors.push(e)
errors.push(e as Error)
}
}

Expand Down
9 changes: 6 additions & 3 deletions src/frameworks/react-intl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class ReactFramework extends Framework {

detection= {
packageJSON: [
'react-intl'
'react-intl',
],
}

Expand All @@ -21,8 +21,11 @@ class ReactFramework extends Framework {

// for visualize the regex, you can use https://regexper.com/
usageMatchRegex = [
// general jsx attrs
'[^\\w\\d](?:i18nKey=|FormattedMessage[ (]\\s*id=|t\\(\\s*)[\'"`]({key})[\'"`]',
// Support for i18nKey= and t( calls, key supports single, double, and back quotes
'[^\\w\\d](?:i18nKey=|t\\(\\s*)[\'"`]({key})[\'"`]',
// Since <FormattedMessage ... id=... /> may have multiple attributes and line breaks, handle it separately
// Allow attribute line breaks and whitespace, support id="xxx.xxx", id={'xxx.xxx'}, etc.
'<FormattedMessage[\\s\\S]*?id=\\s*\\{?\\s*[\'"`]([a-zA-Z0-9_.\\-]+)[\'"`]\\s*\\}?',
// useIntl() hooks, https://github.com/formatjs/react-intl/blob/master/docs/API.md#useintl-hook
'[^\\w\\d](?:formatPlural|formatNumber|formatDate|formatTime|formatHTMLMessage|formatMessage|formatRelativeTime)\\(.*?[\'"`]?id[\'"`]?:\\s*[\'"`]({key})[\'"`]',
'<Trans>({key})<\\/Trans>',
Expand Down
17 changes: 16 additions & 1 deletion src/tagSystems/bcp47.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,22 @@ export class BCP47 extends BaseTagSystem {
if (!locale)
return fallback

return bcp47.stringify(bcp47.parse(locale, { normalize: strict, forgiving: !strict })) || fallback
// First, parse with bcp47
const parsed = bcp47.parse(locale, { normalize: strict, forgiving: !strict })
// If the parsed result has a region, or language+region can restore the original locale, use stringify
if (parsed && parsed.language) {
if (parsed.region)
return bcp47.stringify(parsed)
// Compatible with underscore formats like zh_CN, zh_TW, en_US
if (locale.match(/^[a-z]{2,3}[_-][A-Z]{2,4}$/)) {
// Convert to standard BCP47 format zh-CN
return locale.replace('_', '-')
}
// Compatible with cases where only the main language is present
return parsed.language
}
// If parsing fails, return the original locale directly
return locale || fallback
}

toBCP47(locale: string) {
Expand Down