Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Adding new scopeRangeRegex config to the custom framework o… #926

Merged
merged 2 commits into from
Aug 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
languageIds:
- javascript
- typescript
- javascriptreact
- typescriptreact
scopeRangeRegex: "customScopeRangeFn\\(\\s*\\[?\\s*['\"`](.*?)['\"`]"
monopoly: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"i18n-ally.localesPaths": "public/locales",
"i18n-ally.enabledFrameworks": ["react", "i18next", "custom"],
"i18n-ally.namespace": true,
"i18n-ally.pathMatcher": "{locale}/{namespaces}.json",
"i18n-ally.keystyle": "nested"
}
12 changes: 12 additions & 0 deletions examples/by-features/custom-scope-range/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "custom-scope-range",
"version": "0.1.0",
"private": true,
"dependencies": {
"i18next": "20.3.0",
"i18next-xhr-backend": "3.2.2",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-i18next": "11.9.0"
}
}
15 changes: 15 additions & 0 deletions examples/by-features/custom-scope-range/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"title": "Home"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"title": "hello",
"description": {
"part1": "To get started, edit <1>src/App.js</1> and save to reload.",
"part2": "Switch language between english and german using buttons above."
},
"titlew": "ok",
"foo": {
"bar": "foobar"
}
}
10 changes: 10 additions & 0 deletions examples/by-features/custom-scope-range/src/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.App {
text-align: center;
}

.App-header {
background-color: #222;
height: 100px;
padding: 20px;
color: white;
}
78 changes: 78 additions & 0 deletions examples/by-features/custom-scope-range/src/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/* eslint-disable no-undef */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-unused-vars */
// eslint-disable-next-line no-use-before-define
import React from 'react'
import { Trans } from 'react-i18next'
import { customScopeRangeFn } from './customScopeRange'
import './App.css'

// Component using the Trans component
function MyComponent() {
return (
<Trans i18nKey="translation:description.part1">
To get started, edit <code>src/App.js</code> and save to reload.
</Trans>
)
}

// page uses the hook
function Page() {
const { t } = customScopeRangeFn()

return (
<div className="App">
<div className="App-intro">
<MyComponent />
</div>
<div>{t('translation:description.part2')}</div>
{/* plain <Trans>, #423 */}
<Trans i18nKey="translation:description.part2">Fallback text</Trans>
</div>
)
}

// function with scope
function Page2() {
const { t } = customScopeRangeFn(['translation:foo'])

// inside default namespace ("foo.bar")
t('bar')

// explicit namespace
t('pages.home:title')
t('pages/home:title')
}

// function with another scope
function Page3() {
const { t } = customScopeRangeFn('pages/home')

t('title')

// explicit namespace
t('translation:title')
}

// function with scope in options
function Page4() {
const { t } = customScopeRangeFn('pages/home')

t('title')

// explicit namespace
t('title', { ns: 'translation' })
}

// component with scope in props
function Page5() {
const { t } = customScopeRangeFn('pages/home')

return (
<div className="App">
<Trans t={t} i18nKey="title"></Trans>
{/* explicit namespace */}
<Trans t={t} i18nKey="title" ns="translation"></Trans>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { useTranslation as customScopeRangeFn } from 'react-i18next'
18 changes: 18 additions & 0 deletions examples/by-features/custom-scope-range/src/i18n.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import React from 'react'
import i18n from 'i18next'
import { initReactI18next } from 'react-i18next'

i18n
.use(Backend)
.use(initReactI18next)
.init({
fallbackLng: 'en',
debug: true,

interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
})

export default i18n
8 changes: 8 additions & 0 deletions examples/by-features/custom-scope-range/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars, no-use-before-define
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'

import './i18n'

ReactDOM.render(<App />, document.getElementById('root'))
37 changes: 35 additions & 2 deletions src/frameworks/custom.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import path from 'path'
import fs from 'fs'
import { workspace, FileSystemWatcher } from 'vscode'
import { workspace, FileSystemWatcher, TextDocument } from 'vscode'
import YAML from 'js-yaml'
import { Framework } from './base'
import { Framework, ScopeRange } from './base'
import { Global } from '~/core'
import { LanguageId, File, Log } from '~/utils'

Expand All @@ -11,6 +11,7 @@ const CustomFrameworkConfigFilename = './.vscode/i18n-ally-custom-framework.yml'
interface CustomFrameworkConfig {
languageIds?: LanguageId[] | LanguageId
usageMatchRegex?: string[] | string
scopeRangeRegex?: string
refactorTemplates?: string[]
monopoly?: boolean

Expand Down Expand Up @@ -81,6 +82,38 @@ class CustomFramework extends Framework {
.map(i => i.replace(/\$1/g, keypath))
}

getScopeRange(document: TextDocument): ScopeRange[] | undefined {
if (!this.data?.scopeRangeRegex)
return undefined

if (!this.languageIds.includes(document.languageId as any))
return

const ranges: ScopeRange[] = []
const text = document.getText()
const reg = new RegExp(this.data.scopeRangeRegex, 'g')

for (const match of text.matchAll(reg)) {
if (match?.index == null)
continue

// end previous scope
if (ranges.length)
ranges[ranges.length - 1].end = match.index

// start new scope if namespace provides
if (match[1]) {
ranges.push({
start: match.index,
end: text.length,
namespace: match[1] as string,
})
}
}

return ranges
}

startWatch(root?: string) {
if (this.watchingFor) {
this.watchingFor = undefined
Expand Down