Skip to content

Commit 9c9b445

Browse files
committed
feat(compiler): inject locale data into server runtime components
1 parent bc0cdc3 commit 9c9b445

2 files changed

Lines changed: 123 additions & 36 deletions

File tree

packages/compiler/src/compiler/scope/attribute.ts

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export class ReplexicaAttributeScope extends ReplexicaBaseScope implements IRepl
5757
return this._id;
5858
}
5959

60-
public injectIntl(fileId: string, isServer: boolean): ReplexicaScopeData {
60+
public injectIntl(fileId: string, isServer: boolean, i18nImportPrefix: string): ReplexicaScopeData {
6161
const result: ReplexicaScopeData = {};
6262
if (!this._chunk) { return result; }
6363

@@ -79,22 +79,22 @@ export class ReplexicaAttributeScope extends ReplexicaBaseScope implements IRepl
7979

8080
const isProxyAlreadyApplied = t.isJSXIdentifier(jsxElement.node.openingElement.name) && jsxElement.node.openingElement.name.name === helperName;
8181
if (!isProxyAlreadyApplied) {
82-
// 1. add __ReplexicaComponent attribute to the element and set it to the original component name / identifier / member expression
82+
// 1. add _ReplexicaComponent attribute to the element and set it to the original component name / identifier / member expression
8383
if (t.isJSXIdentifier(jsxElement.node.openingElement.name)) {
8484
// if it's an identifier, it's a native element or a component
8585
if (/^[a-z]/.test(jsxElement.node.openingElement.name.name)) {
8686
// if it's lowercased identifier, it's a native element
8787
jsxElement.node.openingElement.attributes.push(
8888
t.jSXAttribute(
89-
t.jSXIdentifier('__ReplexicaComponent'),
89+
t.jSXIdentifier('_ReplexicaComponent'),
9090
t.stringLiteral(jsxElement.node.openingElement.name.name),
9191
),
9292
);
9393
} else {
9494
// if it's uppercased identifier, it's a component
9595
jsxElement.node.openingElement.attributes.push(
9696
t.jSXAttribute(
97-
t.jSXIdentifier('__ReplexicaComponent'),
97+
t.jSXIdentifier('_ReplexicaComponent'),
9898
t.jSXExpressionContainer(t.identifier(jsxElement.node.openingElement.name.name)),
9999
),
100100
);
@@ -103,7 +103,7 @@ export class ReplexicaAttributeScope extends ReplexicaBaseScope implements IRepl
103103
const memberExpression = parseMemberExpressionFromJsxMemberExpression(jsxElement.node.openingElement.name);
104104
jsxElement.node.openingElement.attributes.push(
105105
t.jSXAttribute(
106-
t.jSXIdentifier('__ReplexicaComponent'),
106+
t.jSXIdentifier('_ReplexicaComponent'),
107107
t.jSXExpressionContainer(memberExpression),
108108
),
109109
);
@@ -117,15 +117,15 @@ export class ReplexicaAttributeScope extends ReplexicaBaseScope implements IRepl
117117
}
118118
}
119119

120-
// add the current attribute to the proxy component's __ReplexicaAttributes attribute
121-
// like so: <ProxyComponent __ReplexicaAttributes={{ [attributeName]: { fileId, scopeId, chunkId } }} />
122-
// create __ReplexicaAttributes attribute entry only if it doesn't exist yet
120+
// add the current attribute to the proxy component's _ReplexicaAttributes attribute
121+
// like so: <ProxyComponent _ReplexicaAttributes={{ [attributeName]: { fileId, scopeId, chunkId } }} />
122+
// create _ReplexicaAttributes attribute entry only if it doesn't exist yet
123123
let systemReplexicaAttribute = jsxElement.node.openingElement.attributes.find((attr) => {
124-
return t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name) && attr.name.name === '__ReplexicaAttributes';
124+
return t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name) && attr.name.name === '_ReplexicaAttributes';
125125
}) as t.JSXAttribute | undefined;
126126
if (!systemReplexicaAttribute) {
127127
systemReplexicaAttribute = t.jSXAttribute(
128-
t.jSXIdentifier('__ReplexicaAttributes'),
128+
t.jSXIdentifier('_ReplexicaAttributes'),
129129
t.jSXExpressionContainer(t.objectExpression([])),
130130
);
131131
jsxElement.node.openingElement.attributes.push(systemReplexicaAttribute);
@@ -142,9 +142,69 @@ export class ReplexicaAttributeScope extends ReplexicaBaseScope implements IRepl
142142
t.objectProperty(t.stringLiteral('chunkId'), t.stringLiteral(this._chunk.id)),
143143
]),
144144
);
145-
// add the current attribute entry to the __ReplexicaAttributes attribute
145+
// add the current attribute entry to the _ReplexicaAttributes attribute
146146
if (t.isJSXExpressionContainer(systemReplexicaAttribute.value) && t.isObjectExpression(systemReplexicaAttribute.value.expression)) {
147147
systemReplexicaAttribute.value.expression.properties.push(selectorProperty);
148+
149+
if (isServer) {
150+
// make sure the following import is available in the file:
151+
// import { loadLocaleFromCookie } from '@replexica/react/next';
152+
let localeLoaderImportName = getImportName(programNode, '@replexica/react/next', 'loadLocaleFromCookie');
153+
if (!localeLoaderImportName) {
154+
localeLoaderImportName = injectImport(programNode, '@replexica/react/next', 'loadLocaleFromCookie');
155+
}
156+
// add the following props to the injected element:
157+
// loadLocale={loadLocaleFromCookie}
158+
jsxElement.node.openingElement.attributes.push(
159+
t.jsxAttribute(
160+
t.jsxIdentifier('loadLocale'),
161+
t.jsxExpressionContainer(t.identifier(localeLoaderImportName)),
162+
)
163+
);
164+
// make sure the following import is available in the file:
165+
// import { loadLocaleData } from '@replexica/react/next';
166+
let localeDataLoaderImportName = getImportName(programNode, '@replexica/react/next', 'loadLocaleData');
167+
if (!localeDataLoaderImportName) {
168+
localeDataLoaderImportName = injectImport(programNode, '@replexica/react/next', 'loadLocaleData');
169+
}
170+
// add the following props to the injected element:
171+
// loadLocaleData={(locale) => loadLocaleData(i18nImportPrefix, locale)}
172+
// jsxElement.node.openingElement.attributes.push(
173+
// t.jsxAttribute(
174+
// t.jsxIdentifier('loadLocaleData'),
175+
// t.jsxExpressionContainer(
176+
// t.arrowFunctionExpression(
177+
// [t.identifier('locale')],
178+
// t.callExpression(
179+
// t.identifier(localeDataLoaderImportName),
180+
// [t.stringLiteral(i18nImportPrefix), t.identifier('locale')],
181+
// ),
182+
// ),
183+
// ),
184+
// )
185+
// );
186+
187+
// add the following props to the injected element:
188+
// loadLocaleData={(locale) => import(`${i18nImportPrefix}/${locale}.json`)}
189+
jsxElement.node.openingElement.attributes.push(
190+
t.jsxAttribute(
191+
t.jsxIdentifier('loadLocaleData'),
192+
t.jsxExpressionContainer(
193+
t.arrowFunctionExpression(
194+
[t.identifier('locale')],
195+
t.callExpression(
196+
t.identifier('import'),
197+
[t.templateLiteral([
198+
t.templateElement({ raw: `${i18nImportPrefix}/`, cooked: `${i18nImportPrefix}/` }, false),
199+
t.templateElement({ raw: '.json', cooked: '.json' }, true),
200+
], [t.identifier('locale')])],
201+
),
202+
),
203+
),
204+
)
205+
);
206+
}
207+
148208
result[this._chunk.id] = this._chunk.text;
149209
}
150210

packages/compiler/src/compiler/scope/content.ts

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -83,34 +83,61 @@ export class ReplexicaContentScope extends ReplexicaBaseScope implements IReplex
8383
);
8484

8585
if (isServer) {
86-
// add the following prop to the injected element:
87-
// importer={(locale) => import(`./${i18nImportPrefix}/${locale}.json`).then((m) => m.default)}
88-
const importer = t.arrowFunctionExpression(
89-
[t.identifier('locale')],
90-
t.callExpression(
91-
t.memberExpression(
92-
t.callExpression(t.identifier('import'), [
93-
t.templateLiteral([
94-
t.templateElement({ raw: `./${i18nImportPrefix}/`, cooked: `./${i18nImportPrefix}/` }, false),
95-
t.templateElement({ raw: '.json', cooked: '.json' }, true),
96-
], [t.identifier('locale')]),
97-
]),
98-
t.identifier('then'),
99-
),
100-
[
101-
t.arrowFunctionExpression(
102-
[t.identifier('m')],
103-
t.memberExpression(t.identifier('m'), t.identifier('default')),
104-
),
105-
],
106-
),
86+
// make sure the following import is available in the file:
87+
// import { loadLocaleFromCookie } from '@replexica/react/next';
88+
let localeLoaderImportName = getImportName(programNode, '@replexica/react/next', 'loadLocaleFromCookie');
89+
if (!localeLoaderImportName) {
90+
localeLoaderImportName = injectImport(programNode, '@replexica/react/next', 'loadLocaleFromCookie');
91+
}
92+
// add the following props to the injected element:
93+
// loadLocale={loadLocaleFromCookie}
94+
injectedElement.attributes.push(
95+
t.jsxAttribute(
96+
t.jsxIdentifier('loadLocale'),
97+
t.jsxExpressionContainer(t.identifier(localeLoaderImportName)),
98+
)
10799
);
108-
100+
// make sure the following import is available in the file:
101+
// import { loadLocaleData } from '@replexica/react/next';
102+
let localeDataLoaderImportName = getImportName(programNode, '@replexica/react/next', 'loadLocaleData');
103+
if (!localeDataLoaderImportName) {
104+
localeDataLoaderImportName = injectImport(programNode, '@replexica/react/next', 'loadLocaleData');
105+
}
106+
// add the following props to the injected element:
107+
// loadLocaleData={(locale) => loadLocaleData(i18nImportPrefix, locale)}
108+
// injectedElement.attributes.push(
109+
// t.jsxAttribute(
110+
// t.jsxIdentifier('loadLocaleData'),
111+
// t.jsxExpressionContainer(
112+
// t.arrowFunctionExpression(
113+
// [t.identifier('locale')],
114+
// t.callExpression(
115+
// t.identifier(localeDataLoaderImportName),
116+
// [t.stringLiteral(i18nImportPrefix), t.identifier('locale')],
117+
// ),
118+
// ),
119+
// ),
120+
// )
121+
// );
122+
123+
// add the following props to the injected element:
124+
// loadLocaleData={(locale) => import(`${i18nImportPrefix}/${locale}.json`)}
109125
injectedElement.attributes.push(
110126
t.jsxAttribute(
111-
t.jsxIdentifier('importer'),
112-
t.jsxExpressionContainer(importer),
113-
),
127+
t.jsxIdentifier('loadLocaleData'),
128+
t.jsxExpressionContainer(
129+
t.arrowFunctionExpression(
130+
[t.identifier('locale')],
131+
t.callExpression(
132+
t.identifier('import'),
133+
[t.templateLiteral([
134+
t.templateElement({ raw: `${i18nImportPrefix}/`, cooked: `${i18nImportPrefix}/` }, false),
135+
t.templateElement({ raw: '.json', cooked: '.json' }, true),
136+
], [t.identifier('locale')])],
137+
),
138+
),
139+
),
140+
)
114141
);
115142
}
116143

0 commit comments

Comments
 (0)