👽🔨 ajoute un script de traduction automatique des règles
Ainsi qu'une tâche circle ci pour vérifier qu'il ne manque pas des traductions de règlespull/855/head
parent
a393dbe948
commit
efbaaa742e
|
@ -37,7 +37,13 @@ jobs:
|
|||
- install
|
||||
- run: |
|
||||
yarn run type-check
|
||||
|
||||
i18n-check:
|
||||
docker:
|
||||
- image: node
|
||||
steps:
|
||||
- install
|
||||
- run: |
|
||||
yarn run i18n:check-rules
|
||||
unit-test:
|
||||
docker:
|
||||
- image: node
|
||||
|
@ -91,6 +97,7 @@ workflows:
|
|||
test:
|
||||
jobs:
|
||||
- type-check
|
||||
- i18n-check
|
||||
- unit-test
|
||||
- end-to-end-test
|
||||
- production-end-to-end-test:
|
||||
|
|
|
@ -89,6 +89,8 @@
|
|||
"type-check": "tsc --noEmit",
|
||||
"compile-lib": "yarn webpack --config source/webpack.lib.js",
|
||||
"compile-dev": "FR_SITE='http://localhost:5000${path}' EN_SITE='http://localhost:5001${path}' yarn run compile",
|
||||
"i18n:check-rules": "node source/scripts/check-missing-translation.js",
|
||||
"i18n:translate-rules": "node source/scripts/automatic-translate.js",
|
||||
"mon-entreprise:serve": "PORT=5000 serve --config serve.mon-entreprise.json --no-clipboard",
|
||||
"mon-entreprise:test": "cypress open --browser chromium",
|
||||
"mycompanyinfrance:serve": "PORT=5001 serve --config serve.infrance.json --no-clipboard",
|
||||
|
|
|
@ -635,7 +635,15 @@ simulateurs:
|
|||
titre: Before starting...
|
||||
plus: Read explanations
|
||||
urssaf: The figures are indicative and do not replace the actual accounts of the Urssaf, impots.gouv.fr, etc
|
||||
auto-entrepreneur: Self-employed entrepreneurs cannot deduct their expenses from their turnover. Therefore, <3>all costs related to the business must be deducted on a net basis to obtain the actual income received</3>.
|
||||
auto-entrepreneur: |
|
||||
Self-employed entrepreneurs cannot deduct their expenses
|
||||
from their turnover. Therefore, <3>all costs related to the business must be
|
||||
deducted on a net basis to obtain the actual income received</3>.
|
||||
cfe: >
|
||||
The simulator does not include the corporate property tax (CFE), which is
|
||||
due from the second year of the fiscal year. Its amount varies greatly
|
||||
depending on the company's turnover and domiciliation.
|
||||
<2> More info. </2>
|
||||
précision:
|
||||
défaut: 'Refine the simulation by answering the following questions:'
|
||||
faible: Low accuracy
|
||||
|
|
|
@ -4426,7 +4426,7 @@ dirigeant . auto-entrepreneur . cotisations et contributions . TFC . métiers:
|
|||
- sinon: 0.48%
|
||||
|
||||
dirigeant . auto-entrepreneur . cotisations et contributions . contribution formation professionnelle:
|
||||
titre: Contribution à la formation professionnelle
|
||||
titre: Contribution à la formation professionnelleyay
|
||||
unité par défaut: €/mois
|
||||
références:
|
||||
shine.fr: https://www.shine.fr/blog/formation-professionnelle-auto-entrepreneur/
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,45 @@
|
|||
require('dotenv').config()
|
||||
|
||||
var { safeDump } = require('js-yaml')
|
||||
var fs = require('fs')
|
||||
|
||||
var querystring = require('querystring')
|
||||
require('isomorphic-fetch')
|
||||
const {
|
||||
getMissingTranslations,
|
||||
externalizationPath
|
||||
} = require('./get-missing-translations')
|
||||
|
||||
const [missingTranslations, resolved] = getMissingTranslations()
|
||||
|
||||
fs.writeFileSync(externalizationPath, safeDump(resolved))
|
||||
|
||||
const translateWithDeepl = async text => {
|
||||
const response = await fetch(
|
||||
`https://api.deepl.com/v2/translate?${querystring.stringify({
|
||||
text,
|
||||
auth_key: process.env.DEEPL_API_SECRET,
|
||||
source_lang: 'FR',
|
||||
target_lang: 'EN'
|
||||
})}`
|
||||
)
|
||||
const { translations } = await response.json()
|
||||
return translations[0].text
|
||||
}
|
||||
|
||||
missingTranslations.length &&
|
||||
console.log(
|
||||
`Fetch translation for: \n${missingTranslations
|
||||
.map(([dottedName, attr]) => `\t- ${dottedName} [${attr}]\n`)
|
||||
.join('')}`
|
||||
)
|
||||
missingTranslations.forEach(async ([dottedName, attr, value]) => {
|
||||
try {
|
||||
const translation = await translateWithDeepl(value)
|
||||
resolved[dottedName][attr] = translation
|
||||
// C'est très bourrin, mais on ne veut pas perdre une traduction qu'on a payé
|
||||
fs.writeFileSync(externalizationPath, safeDump(resolved))
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
})
|
|
@ -0,0 +1,13 @@
|
|||
const { getMissingTranslations } = require('./get-missing-translations')
|
||||
|
||||
const missingTranslations = getMissingTranslations()[0]
|
||||
|
||||
if (missingTranslations.length) {
|
||||
throw new Error(
|
||||
`Il manque les traductions suivantes dans 'externalized.yaml' : \n${missingTranslations
|
||||
.map(([dottedName, attr]) => `\t- ${dottedName} [${attr}]\n`)
|
||||
.join(
|
||||
''
|
||||
)}\nUtilisez la commande suivante pour traduire automatiquement les clés manquantes :\n\n\tyarn run i18n:translate-rules\n`
|
||||
)
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
var { safeLoad, safeDump } = require('js-yaml')
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
let R = require('ramda')
|
||||
|
||||
let externalizationPath = 'source/règles/externalized.yaml'
|
||||
|
||||
let rules = safeLoad(
|
||||
fs.readFileSync(path.resolve('source/règles/base.yaml'), 'utf-8')
|
||||
)
|
||||
|
||||
let currentExternalization = safeLoad(
|
||||
fs.readFileSync(path.resolve(externalizationPath), 'utf-8')
|
||||
)
|
||||
|
||||
let attributesToExternalize = [
|
||||
'titre',
|
||||
'description',
|
||||
'question',
|
||||
'résumé',
|
||||
'suggestions',
|
||||
'contrôles'
|
||||
]
|
||||
|
||||
let resolved = Object.entries(rules)
|
||||
.map(([dottedName, rule]) => [
|
||||
dottedName,
|
||||
!rule || !rule.titre
|
||||
? { ...rule, titre: dottedName.split(' . ').slice(-1)[0] }
|
||||
: rule
|
||||
])
|
||||
.map(([dottedName, rule]) => ({
|
||||
[dottedName]: R.mergeAll(
|
||||
R.toPairs(rule)
|
||||
.filter(([, v]) => !!v)
|
||||
.map(([k, v]) => {
|
||||
let attrToTranslate = attributesToExternalize.find(R.equals(k))
|
||||
if (!attrToTranslate) return {}
|
||||
let enTrad = attrToTranslate + '.en',
|
||||
frTrad = attrToTranslate + '.fr'
|
||||
|
||||
let currentTranslation = currentExternalization[dottedName]
|
||||
//Check if a human traduction exists already for this attribute
|
||||
if (currentTranslation && currentTranslation[enTrad])
|
||||
return {
|
||||
[enTrad]: currentTranslation[enTrad],
|
||||
[frTrad]: v
|
||||
}
|
||||
|
||||
return {
|
||||
[enTrad]: '!!' + v,
|
||||
[frTrad]: v
|
||||
}
|
||||
})
|
||||
)
|
||||
}))
|
||||
fs.writeFileSync(externalizationPath, safeDump(R.mergeAll(resolved)))
|
|
@ -0,0 +1,75 @@
|
|||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
let R = require('ramda')
|
||||
|
||||
let { safeLoad } = require('js-yaml')
|
||||
let externalizationPath = 'source/règles/externalized.yaml'
|
||||
|
||||
let rules = safeLoad(
|
||||
fs.readFileSync(path.resolve('source/règles/base.yaml'), 'utf-8')
|
||||
)
|
||||
|
||||
let currentExternalization = safeLoad(
|
||||
fs.readFileSync(path.resolve(externalizationPath), 'utf-8')
|
||||
)
|
||||
|
||||
let attributesToExternalize = [
|
||||
'titre',
|
||||
'description',
|
||||
'question',
|
||||
'résumé',
|
||||
'suggestions',
|
||||
'contrôles'
|
||||
]
|
||||
|
||||
function getMissingTranslations() {
|
||||
let missingTranslations = []
|
||||
let resolved = Object.entries(rules)
|
||||
.map(([dottedName, rule]) => [
|
||||
dottedName,
|
||||
!rule || !rule.titre
|
||||
? { ...rule, titre: dottedName.split(' . ').slice(-1)[0] }
|
||||
: rule
|
||||
])
|
||||
.map(([dottedName, rule]) => ({
|
||||
[dottedName]: R.mergeAll(
|
||||
R.toPairs(rule)
|
||||
.filter(([, v]) => !!v)
|
||||
.map(([k, v]) => {
|
||||
let attrToTranslate = attributesToExternalize.find(R.equals(k))
|
||||
if (!attrToTranslate) return {}
|
||||
let enTrad = attrToTranslate + '.en',
|
||||
frTrad = attrToTranslate + '.fr'
|
||||
|
||||
let currentTranslation = currentExternalization[dottedName]
|
||||
// Check if a human traduction exists already for this attribute and if
|
||||
// it does need to be updated
|
||||
if (
|
||||
currentTranslation &&
|
||||
currentTranslation[enTrad] &&
|
||||
currentTranslation[frTrad] === v
|
||||
)
|
||||
return {
|
||||
[enTrad]: currentTranslation[enTrad],
|
||||
[frTrad]: v
|
||||
}
|
||||
if (['contrôles', 'suggestions'].includes(attrToTranslate)) {
|
||||
return {
|
||||
[frTrad]: v
|
||||
}
|
||||
}
|
||||
missingTranslations.push([dottedName, enTrad, v])
|
||||
return {
|
||||
[frTrad]: v
|
||||
}
|
||||
})
|
||||
)
|
||||
}))
|
||||
resolved = R.mergeAll(resolved)
|
||||
return [missingTranslations, resolved]
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getMissingTranslations,
|
||||
externalizationPath
|
||||
}
|
Loading…
Reference in New Issue