🔥 meilleure prise en charge de la traduction
- Les traductions sont désormais récupérées uniquement pour le site anglais - Engine ne dépend plus des traductionspull/949/head
parent
3e8c7b4b26
commit
4020e49871
|
@ -17,7 +17,7 @@ export type Action =
|
|||
| HideControlAction
|
||||
| LoadPreviousSimulationAction
|
||||
| SetSituationBranchAction
|
||||
| UpdateDefaultUnit
|
||||
| UpdateDefaultUnitAction
|
||||
| SetActiveTargetAction
|
||||
|
||||
export type ThunkResult<R> = ThunkAction<
|
||||
|
@ -64,7 +64,7 @@ type SetSituationBranchAction = ReturnType<typeof setSituationBranch>
|
|||
type SetActiveTargetAction = ReturnType<typeof setActiveTarget>
|
||||
type HideControlAction = ReturnType<typeof hideControl>
|
||||
type ExplainVariableAction = ReturnType<typeof explainVariable>
|
||||
type UpdateDefaultUnit = ReturnType<typeof updateUnit>
|
||||
type UpdateDefaultUnitAction = ReturnType<typeof updateUnit>
|
||||
|
||||
export const resetSimulation = () =>
|
||||
({
|
||||
|
|
|
@ -27,6 +27,7 @@ type Cache = {
|
|||
}
|
||||
}
|
||||
|
||||
export { default as translateRules } from './translateRules'
|
||||
export { parseRules }
|
||||
export default class Engine {
|
||||
parsedRules: Record<DottedName, Rule>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import {
|
||||
assoc,
|
||||
dropLast,
|
||||
filter,
|
||||
isNil,
|
||||
|
@ -9,7 +8,6 @@ import {
|
|||
pipe,
|
||||
propEq,
|
||||
range,
|
||||
reduce,
|
||||
reject,
|
||||
split,
|
||||
take
|
||||
|
@ -72,70 +70,6 @@ export function collectDefaults(parsedRules) {
|
|||
Autres
|
||||
*/
|
||||
|
||||
/* Traduction */
|
||||
const translateContrôle = (prop, rule, translation, lang) =>
|
||||
assoc(
|
||||
'contrôles',
|
||||
rule.contrôles.map((control, i) => ({
|
||||
...control,
|
||||
message: translation[`${prop}.${i}.${lang}`]?.replace(
|
||||
/^\[automatic\] /,
|
||||
''
|
||||
)
|
||||
})),
|
||||
rule
|
||||
)
|
||||
const translateSuggestion = (prop, rule, translation, lang) =>
|
||||
assoc(
|
||||
'suggestions',
|
||||
Object.entries(rule.suggestions).reduce(
|
||||
(acc, [name, value]) => ({
|
||||
...acc,
|
||||
[translation[`${prop}.${name}.${lang}`]?.replace(
|
||||
/^\[automatic\] /,
|
||||
''
|
||||
)]: value
|
||||
}),
|
||||
{}
|
||||
),
|
||||
rule
|
||||
)
|
||||
|
||||
export const attributesToTranslate = [
|
||||
'titre',
|
||||
'description',
|
||||
'question',
|
||||
'résumé',
|
||||
'suggestions',
|
||||
'contrôles',
|
||||
'note'
|
||||
]
|
||||
|
||||
export let translateAll = (translations, flatRules) => {
|
||||
let translationsOf = rule => translations[rule.dottedName],
|
||||
translateProp = (lang, translation) => (rule, prop) => {
|
||||
if (prop === 'contrôles' && rule?.contrôles) {
|
||||
return translateContrôle(prop, rule, translation, lang)
|
||||
}
|
||||
if (prop === 'suggestions' && rule?.suggestions) {
|
||||
return translateSuggestion(prop, rule, translation, lang)
|
||||
}
|
||||
let propTrans = translation[prop + '.' + lang]
|
||||
propTrans = propTrans?.replace(/^\[automatic\] /, '')
|
||||
return propTrans ? assoc(prop, propTrans, rule) : rule
|
||||
},
|
||||
translateRule = (lang, translations, props) => rule => {
|
||||
let ruleTrans = translationsOf(rule)
|
||||
return ruleTrans
|
||||
? reduce(translateProp(lang, ruleTrans), rule, props)
|
||||
: rule
|
||||
}
|
||||
return map(
|
||||
translateRule('en', translations, attributesToTranslate),
|
||||
flatRules
|
||||
)
|
||||
}
|
||||
|
||||
export let findParentDependencies = (rules, rule) => {
|
||||
// A parent dependency means that one of a rule's parents is not just a namespace holder, it is a boolean question. E.g. is it a fixed-term contract, yes / no
|
||||
// When it is resolved to false, then the whole branch under it is disactivated (non applicable)
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
import { assoc } from 'ramda'
|
||||
|
||||
/* Traduction */
|
||||
const translateContrôle = (prop, rule, translation, lang) =>
|
||||
assoc(
|
||||
'contrôles',
|
||||
rule.contrôles.map((control, i) => ({
|
||||
...control,
|
||||
message: translation[`${prop}.${i}.${lang}`]?.replace(
|
||||
/^\[automatic\] /,
|
||||
''
|
||||
)
|
||||
})),
|
||||
rule
|
||||
)
|
||||
|
||||
const translateSuggestion = (prop, rule, translation, lang) =>
|
||||
assoc(
|
||||
'suggestions',
|
||||
Object.entries(rule.suggestions).reduce(
|
||||
(acc, [name, value]) => ({
|
||||
...acc,
|
||||
[translation[`${prop}.${name}.${lang}`]?.replace(
|
||||
/^\[automatic\] /,
|
||||
''
|
||||
)]: value
|
||||
}),
|
||||
{}
|
||||
),
|
||||
rule
|
||||
)
|
||||
|
||||
export const attributesToTranslate = [
|
||||
'titre',
|
||||
'description',
|
||||
'question',
|
||||
'résumé',
|
||||
'suggestions',
|
||||
'contrôles',
|
||||
'note'
|
||||
]
|
||||
|
||||
const translateProp = (lang, translation) => (rule, prop) => {
|
||||
if (prop === 'contrôles' && rule?.contrôles) {
|
||||
return translateContrôle(prop, rule, translation, lang)
|
||||
}
|
||||
if (prop === 'suggestions' && rule?.suggestions) {
|
||||
return translateSuggestion(prop, rule, translation, lang)
|
||||
}
|
||||
let propTrans = translation[prop + '.' + lang]
|
||||
propTrans = propTrans?.replace(/^\[automatic\] /, '')
|
||||
return propTrans ? assoc(prop, propTrans, rule) : rule
|
||||
}
|
||||
|
||||
const translateRule = (lang, translations, name, rule) => {
|
||||
let ruleTrans = translations[name]
|
||||
if (!ruleTrans) {
|
||||
return rule
|
||||
}
|
||||
return attributesToTranslate.reduce(
|
||||
translateProp(lang, ruleTrans),
|
||||
rule ?? {}
|
||||
)
|
||||
}
|
||||
|
||||
export default function translateRules(lang, translations, rules) {
|
||||
const translatedRules = Object.fromEntries(
|
||||
Object.entries(rules).map(([name, rule]) => [
|
||||
name,
|
||||
translateRule(lang, translations, name, rule)
|
||||
])
|
||||
)
|
||||
return translatedRules
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
'404':
|
||||
action: Return to safe place
|
||||
message: This page does not exist or no longer exists
|
||||
'<0>Covid-19 et chômage partiel </0>: <3>Calculez votre indemnité</3>': '<0>Covid-19 and Short-Time </0>Work: <3>Calculate Your Benefit</3>'
|
||||
<0>Oui</0>: <0>Yes</0>
|
||||
A quoi servent mes cotisations ?: What's included in my contributions?
|
||||
Accueil: Home
|
||||
|
@ -60,7 +61,7 @@ Gérant minoritaire: Managing director
|
|||
Habituellement: Usually
|
||||
Imprimer: Print
|
||||
Impôts: Taxes
|
||||
'Indemnité chômage partiel prise en charge par l''état :': 'State-paid short-time working allowance :'
|
||||
"Indemnité chômage partiel prise en charge par l'état :": 'State-paid short-time working allowance :'
|
||||
Indépendant: Independent
|
||||
International: International
|
||||
Intégrer l'interface de simulation: Integrate the simulation interface
|
||||
|
@ -77,7 +78,7 @@ Mon entreprise: My company
|
|||
Mon revenu: My income
|
||||
Montant: Amount
|
||||
Montant des cotisations: Amount of contributions
|
||||
'Nom de l''entreprise ou SIREN ': Company name or SIREN code
|
||||
"Nom de l'entreprise ou SIREN ": Company name or SIREN code
|
||||
Non: 'No'
|
||||
Nous n'avons rien trouvé: We didn't find any matching registered company.
|
||||
Oui: 'Yes'
|
||||
|
@ -142,7 +143,7 @@ Taux: Rate
|
|||
Taux calculé: Calculated rate
|
||||
Taux moyen: Average rate
|
||||
Total des retenues: Total withheld
|
||||
'Total payé par l''entreprise :': 'Total paid by the company :'
|
||||
"Total payé par l'entreprise :": 'Total paid by the company :'
|
||||
Tout effacer: Delete all
|
||||
Tranche de l'assiette: Scale bracket
|
||||
Un seul associé: Only one partner
|
||||
|
@ -401,9 +402,7 @@ coronavirus:
|
|||
<0>Coronavirus and short-time working: what impact on my income?</0><1>The
|
||||
government is putting in place measures to support employees affected by the
|
||||
Coronavirus crisis. One of the key measures is the assumption of the entire
|
||||
short-time working compensation by the State.</1><2>This simulator allows
|
||||
you to find out your net income if you have been placed on short-time work,
|
||||
as well as the total cost to the company.</2>
|
||||
short-time working compensation by the State.</1>
|
||||
page:
|
||||
description: Estimate net income with short-time working benefits
|
||||
titre: 'Coronavirus and short-time working: what impact on your income?'
|
||||
|
|
|
@ -1,24 +1,21 @@
|
|||
import { Action } from 'Actions/actions'
|
||||
import { Unit } from 'Engine/units'
|
||||
import originRules from 'Publicode/rules'
|
||||
import { defaultTo, identity, omit, without } from 'ramda'
|
||||
import reduceReducers from 'reduce-reducers'
|
||||
import { combineReducers, Reducer } from 'redux'
|
||||
import { analysisWithDefaultsSelector } from 'Selectors/analyseSelectors'
|
||||
import { SavedSimulation } from 'Selectors/storageSelectors'
|
||||
import { DottedName } from 'Types/rule'
|
||||
import { DottedName, Rules } from 'Types/rule'
|
||||
import i18n, { AvailableLangs } from '../i18n'
|
||||
import { areUnitConvertible, convertUnit, parseUnit } from './../engine/units'
|
||||
import inFranceAppReducer, { Company } from './inFranceAppReducer'
|
||||
import storageRootReducer from './storageReducer'
|
||||
|
||||
function rules(state = null, action) {
|
||||
switch (action.type) {
|
||||
case 'SET_RULES':
|
||||
return action.rules
|
||||
default:
|
||||
return state
|
||||
}
|
||||
function rules(state: Rules = originRules) {
|
||||
return state
|
||||
}
|
||||
|
||||
function explainedVariable(
|
||||
state: DottedName | null = null,
|
||||
action: Action
|
||||
|
|
|
@ -5,7 +5,6 @@ import {
|
|||
disambiguateRuleReference,
|
||||
splitName
|
||||
} from 'Engine/ruleUtils'
|
||||
import rules from 'Publicode/rules'
|
||||
import {
|
||||
add,
|
||||
difference,
|
||||
|
@ -54,9 +53,7 @@ let configSelector = (state: RootState) => state.simulation?.config || {}
|
|||
// hot-reloading on developement). See
|
||||
// https://github.com/betagouv/mon-entreprise/issues/912
|
||||
// TOTO
|
||||
const rulesEn = rules
|
||||
let flatRulesSelector = (state: RootState) =>
|
||||
state.rules ?? (state.lang === 'en' ? rulesEn : rules)
|
||||
let flatRulesSelector = (state: RootState) => state.rules
|
||||
|
||||
// We must here compute parsedRules, flatRules, analyse which contains both
|
||||
// targets and cache objects
|
||||
|
|
|
@ -55,7 +55,7 @@ const middlewares = [
|
|||
trackSimulatorActions(tracker)
|
||||
]
|
||||
|
||||
function InFranceRoute({ basename, language }) {
|
||||
function InFranceRoute({ basename, language, rules }) {
|
||||
useEffect(() => {
|
||||
getSessionStorage()?.setItem('lang', language)
|
||||
}, [language])
|
||||
|
@ -73,7 +73,8 @@ function InFranceRoute({ basename, language }) {
|
|||
}}
|
||||
initialStore={{
|
||||
...retrievePersistedState(),
|
||||
previousSimulation: retrievePersistedSimulation()
|
||||
previousSimulation: retrievePersistedSimulation(),
|
||||
rules
|
||||
}}
|
||||
>
|
||||
<RouterSwitch />
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
import 'core-js/stable'
|
||||
import { translateRules } from 'Engine'
|
||||
import rules from 'Publicode/rules'
|
||||
import React from 'react'
|
||||
import { render } from 'react-dom'
|
||||
import 'regenerator-runtime/runtime'
|
||||
import translations from '../../locales/rules-en.yaml'
|
||||
import App from './App'
|
||||
|
||||
let anchor = document.querySelector('#js')
|
||||
render(<App language="en" basename="infrance" />, anchor)
|
||||
console.log(translateRules('en', translations, rules))
|
||||
render(
|
||||
<App
|
||||
language="en"
|
||||
basename="infrance"
|
||||
rules={translateRules('en', translations, rules)}
|
||||
/>,
|
||||
anchor
|
||||
)
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import 'core-js/stable'
|
||||
import rules from 'Publicode/rules'
|
||||
import React from 'react'
|
||||
import { render } from 'react-dom'
|
||||
import 'regenerator-runtime/runtime'
|
||||
import App from './App'
|
||||
|
||||
let anchor = document.querySelector('#js')
|
||||
render(<App language="fr" basename="mon-entreprise" />, anchor)
|
||||
render(<App language="fr" basename="mon-entreprise" rules={rules} />, anchor)
|
||||
|
|
|
@ -139,17 +139,20 @@ function ExplanationSection() {
|
|||
netHabituel,
|
||||
{
|
||||
...net,
|
||||
additionalText: (
|
||||
additionalText: language === 'fr' && (
|
||||
<>
|
||||
Soit{' '}
|
||||
<strong>
|
||||
{formatValue({
|
||||
value: (net.nodeValue / netHabituel.nodeValue) * 100,
|
||||
unit: '%',
|
||||
maximumFractionDigits: 0
|
||||
})}
|
||||
</strong>{' '}
|
||||
du revenu net
|
||||
<Trans>
|
||||
Soit{' '}
|
||||
<strong>
|
||||
{formatValue({
|
||||
value:
|
||||
(net.nodeValue / netHabituel.nodeValue) * 100,
|
||||
unit: '%',
|
||||
maximumFractionDigits: 0
|
||||
})}
|
||||
</strong>{' '}
|
||||
du revenu net
|
||||
</Trans>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -159,7 +162,7 @@ function ExplanationSection() {
|
|||
totalEntrepriseHabituel,
|
||||
{
|
||||
...totalEntreprise,
|
||||
additionalText: (
|
||||
additionalText: language === 'fr' && (
|
||||
<>
|
||||
Soit{' '}
|
||||
<strong>
|
||||
|
|
|
@ -162,8 +162,10 @@ export let SalarySimulation = () => {
|
|||
/>
|
||||
<br />
|
||||
<Banner icon={'😷'}>
|
||||
<strong>Covid-19 et chômage partiel </strong>:{' '}
|
||||
<Link to={sitePaths.coronavirus}>Calculez votre indemnité</Link>
|
||||
<Trans>
|
||||
<strong>Covid-19 et chômage partiel </strong>:{' '}
|
||||
<Link to={sitePaths.coronavirus}>Calculez votre indemnité</Link>
|
||||
</Trans>
|
||||
</Banner>
|
||||
<PreviousSimulationBanner />
|
||||
</>
|
||||
|
|
|
@ -10,25 +10,12 @@ import Landing from './Landing'
|
|||
import Studio from './LazyStudio'
|
||||
import Mécanismes from './Mécanismes'
|
||||
|
||||
function Router({ language }) {
|
||||
function Router({ language, rules }) {
|
||||
useEffect(() => {
|
||||
getSessionStorage()?.setItem('lang', language)
|
||||
}, [language])
|
||||
const rules = language === 'en' ? rules : rules
|
||||
return (
|
||||
<Provider
|
||||
basename="publicodes"
|
||||
language={language}
|
||||
reduxMiddlewares={[]}
|
||||
initialStore={{
|
||||
rules,
|
||||
simulation: {
|
||||
config: {
|
||||
objectifs: []
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Provider basename="publicodes" language={language} rules={rules}>
|
||||
<RouterSwitch />
|
||||
</Provider>
|
||||
)
|
||||
|
|
|
@ -2,6 +2,9 @@ import { Unit } from 'Engine/units'
|
|||
import jsonRules from './dottednames.json'
|
||||
export type DottedName = keyof typeof jsonRules
|
||||
|
||||
// TODO : différencier Rule et ParsedRule
|
||||
export type Rules = { [key in DottedName]: Rule }
|
||||
|
||||
export type Rule = {
|
||||
dottedName: DottedName
|
||||
question?: string
|
||||
|
|
Loading…
Reference in New Issue