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

Venia Localization w/ i18n #2314

Closed

Conversation

chris-brabender
Copy link

@chris-brabender chris-brabender commented Apr 5, 2020

Description

Introduced localised content to PWA Studio.

  • Allows for fetching of translated phrases from Magento backend via CLI tool
  • Allows fetching of available store views from Magento backend at build
  • Allows for definition of store view in GraphQL headers
  • Allows for creation of local / custom translation files in i18n format
  • Allows for venia-ui and peregrine translation files to be included also (fallback)
  • Allows for display of available store views and switching
  • Allows for locale codes to be supplied in url paths to switch locales (eg: /en_us, /fr_fr)

Note: draft PR for feedback and comments

Related Issue

#669

Acceptance

Verification Stakeholders

Specification

Verification Steps

  • Requires Added Magento_TranslationGraphQl module to support PWA Studio Localization magento2#27600 merged to core and one more PR that is yet to be submitted
  • import useLocalization hook from @magento/peregerine to all components with a phrase to be translated
  • Wrap phrases in _t() function
  • Execute yarn run fetch:translations to extract phrase and fetch any available translations from the magento backend
  • Create a core.json file in venia-concept locales for any phrases that may be missing (some examples included for locales folder structure)
  • Build and enjoy localised content

Screenshots / Screen Captures (if appropriate)

Screen Shot 2020-04-05 at 1 29 28 AM
Screen Shot 2020-04-05 at 1 29 34 AM
Screen Shot 2020-04-05 at 1 29 45 AM

Checklist

  • I have updated the documentation accordingly, if necessary.
  • I have added tests to cover my changes, if necessary.

christopher_brabender added 16 commits March 19, 2020 10:40
- Calling Magento API endpoint with extracted phrases now
- Refactored buildpack graphql to support variables
- Updated parse-translations to retrieve locales from magento, query for translations then export json translation files
- Moving fetch of available store views to build time for a) speed and b) simplicity
- Rewrote to handle proper store code setting in graphql and local definition as different variables (store code does not always equal locale)
- Added new cache key for apollo cache for each store view to handle storing responses properly per store view and not getting content flickering
- Overall code tidiness improvements
- Removing redundant imports
- Restoring comment location to original
@PWAStudioBot
Copy link
Contributor

PWAStudioBot commented Apr 7, 2020

Fails
🚫

The following file(s) were not formatted with prettier. Make sure to execute yarn run prettier locally prior to committing.

packages/peregrine/lib/hooks/useLocalization.js
packages/peregrine/lib/Router/resolveUnknownRoute.js
packages/pwa-buildpack/lib/cli/parse-translations.js
packages/venia-concept/src/i18n.js
packages/venia-ui/lib/drivers/adapter.js
🚫

No linked issue found. Please link a relevant open issue by adding the text "closes #<issue_number>" or "closes JIRA-<issue_number>" in your PR.

🚫

Unit tests in the following files did not pass 😔. All tests must pass before this PR can be merged

  • packages/pagebuilder/lib/ContentTypes/Products/__tests__/products.spec.js
  • packages/pagebuilder/lib/ContentTypes/Banner/__tests__/banner.spec.js
  • packages/venia-ui/lib/components/App/__tests__/app.spec.js
  • packages/pagebuilder/lib/ContentTypes/Map/__tests__/map.spec.js
  • packages/venia-ui/lib/components/ProductImageCarousel/__tests__/carousel.spec.js
  • packages/venia-ui/lib/components/Checkout/__tests__/editableForm.spec.js
  • packages/peregrine/lib/Router/__tests__/resolveUnknownRoute.test.js
  • packages/peregrine/lib/talons/Navigation/__tests__/useNavigation.spec.js
  • packages/peregrine/lib/Router/__tests__/magentoRouteHandler.test.js
  • packages/pagebuilder/lib/ContentTypes/Row/__tests__/row.spec.js
  • packages/venia-ui/lib/components/CartPage/PriceSummary/__tests__/priceSummary.spec.js
  • packages/venia-ui/lib/components/SignIn/__tests__/signIn.spec.js
  • packages/venia-ui/lib/components/Checkout/__tests__/paymentsForm.spec.js
  • packages/peregrine/lib/talons/CartPage/ProductListing/__tests__/useQuantity.spec.js
  • packages/venia-ui/lib/components/CartPage/PriceAdjustments/ShippingMethods/__tests__/shippingForm.spec.js
  • packages/peregrine/lib/talons/FilterModal/__tests__/useFilterModal.spec.js
  • packages/peregrine/lib/context/__tests__/cart.spec.js
  • packages/pagebuilder/lib/ContentTypes/Column/__tests__/column.spec.js
  • packages/venia-ui/lib/components/MiniCart/__tests__/miniCart.spec.js
  • packages/venia-ui/lib/components/CartPage/PriceAdjustments/CouponCode/__tests__/couponCode.spec.js
  • packages/venia-ui/lib/components/CategoryList/__tests__/categoryList.spec.js
  • packages/pagebuilder/lib/ContentTypes/ButtonItem/__tests__/buttonItem.spec.js
  • packages/venia-ui/lib/components/ProductFullDetail/__tests__/productFullDetail.spec.js
  • packages/venia-ui/lib/components/Navigation/__tests__/navigation.spec.js
  • packages/peregrine/lib/talons/CartPage/ProductListing/__tests__/useProduct.spec.js
  • packages/pagebuilder/lib/__tests__/factory.spec.js
  • packages/venia-concept/src/__tests__/index.spec.js
  • packages/pagebuilder/lib/ContentTypes/Tabs/__tests__/tabs.spec.js
  • packages/peregrine/lib/talons/Image/__tests__/useResourceImage.spec.js
  • packages/peregrine/lib/talons/CartPage/GiftCards/__tests__/useGiftCards.spec.js
  • packages/venia-ui/lib/components/CartPage/ProductListing/__tests__/product.spec.js
  • packages/venia-ui/lib/components/CartPage/GiftCards/__tests__/giftCards.spec.js
  • packages/venia-ui/lib/components/Checkout/__tests__/braintreeDropin.spec.js
  • packages/venia-ui/lib/components/CartPage/PriceAdjustments/ShippingMethods/__tests__/shippingMethods.spec.js
  • packages/venia-ui/lib/components/Checkout/__tests__/overview.spec.js
  • packages/venia-ui/lib/components/ProductOptions/__tests__/option.spec.js
  • packages/venia-ui/lib/components/Checkout/__tests__/addressForm.spec.js
  • packages/venia-ui/lib/components/CartPage/__tests__/cartPage.spec.js
  • packages/venia-ui/lib/components/MiniCart/__tests__/editItem.spec.js
  • packages/venia-ui/lib/components/SearchBar/__tests__/searchBar.spec.js
  • packages/venia-ui/lib/components/Checkout/__tests__/form.spec.js
  • packages/peregrine/lib/context/__tests__/checkout.spec.js
  • packages/venia-ui/lib/components/SearchBar/__tests__/suggestions.spec.js
  • packages/peregrine/lib/context/__tests__/catalog.spec.js
  • packages/peregrine/lib/context/__tests__/user.spec.js
  • packages/peregrine/lib/context/__tests__/app.spec.js
  • packages/venia-ui/lib/components/Breadcrumbs/__tests__/breadcrumbs.spec.js
  • packages/venia-ui/lib/components/Image/___tests__/image.spec.js
  • packages/pagebuilder/lib/ContentTypes/Block/__tests__/block.spec.js
  • packages/venia-ui/lib/components/Image/___tests__/resourceImage.spec.js
  • packages/venia-ui/lib/components/CartPage/PriceSummary/__tests__/giftCardSummary.spec.js
  • packages/venia-ui/lib/components/SearchBar/__tests__/searchField.spec.js
  • packages/venia-ui/lib/components/CartPage/PriceSummary/__tests__/discountSummary.spec.js
  • packages/peregrine/lib/talons/Image/__tests__/usePlaceholderImage.spec.js
  • packages/venia-ui/lib/components/CartPage/PriceSummary/__tests__/taxSummary.spec.js
  • packages/peregrine/lib/talons/Image/__tests__/useImage.spec.js
  • packages/peregrine/lib/context/__tests__/unhandledErrors.spec.js
  • packages/peregrine/lib/talons/CartPage/PriceAdjustments/__tests__/useCouponCode.spec.js
  • packages/venia-ui/lib/components/Image/___tests__/placeholderImage.spec.js
  • packages/venia-ui/lib/components/Navigation/__tests__/navHeader.spec.js
  • packages/pagebuilder/lib/ContentTypes/Video/__tests__/video.spec.js
  • packages/venia-ui/lib/components/Checkbox/__tests__/checkbox.spec.js
  • packages/venia-ui/lib/components/CartPage/PriceSummary/__tests__/shippingSummary.spec.js
  • packages/venia-ui/lib/components/ProductImageCarousel/__tests__/thumbnail.spec.js
  • packages/pagebuilder/lib/ContentTypes/Image/__tests__/image.spec.js
  • packages/pagebuilder/lib/ContentTypes/Buttons/__tests__/buttons.spec.js
  • packages/venia-ui/lib/components/CartPage/ProductListing/__tests__/productListing.spec.js
  • packages/venia-ui/lib/components/Gallery/__tests__/gallery.spec.js
  • packages/venia-ui/lib/components/CartPage/PriceAdjustments/ShippingMethods/__tests__/shippingRadios.spec.js
  • packages/venia-ui/lib/components/MiniCart/__tests__/product.spec.js
  • packages/pagebuilder/lib/ContentTypes/TabItem/__tests__/tabItem.spec.js
  • packages/peregrine/lib/talons/CartPage/__tests__/useCartPage.spec.js
  • packages/pagebuilder/lib/ContentTypes/Slider/__tests__/slider.spec.js
  • packages/venia-ui/lib/components/Gallery/__tests__/item.spec.js
  • packages/venia-ui/lib/components/CreateAccount/__tests__/createAccount.spec.js
  • packages/venia-ui/lib/components/Header/__tests__/cartTrigger.spec.js
  • packages/venia-ui/lib/components/CartPage/GiftCards/__tests__/giftCard.spec.js
  • packages/venia-ui/lib/components/MiniCart/__tests__/cartOptions.spec.js
  • packages/venia-ui/lib/components/CartPage/ProductListing/EditModal/__tests__/productForm.spec.js
  • packages/venia-ui/lib/components/SearchBar/__tests__/suggestedProducts.spec.js
  • packages/venia-ui/lib/components/Pagination/__tests__/pagination.spec.js
  • packages/venia-ui/lib/RootComponents/Category/__tests__/categoryContent.spec.js
  • packages/venia-ui/lib/components/CartPage/ProductListing/EditModal/__tests__/editModal.spec.js
  • packages/venia-ui/lib/components/CategoryTree/__tests__/categoryTree.spec.js
  • packages/venia-ui/lib/components/CategoryTree/__tests__/categoryLeaf.spec.js
  • packages/venia-ui/lib/components/SearchBar/__tests__/suggestedCategories.spec.js
  • packages/pagebuilder/lib/ContentTypes/Heading/__tests__/heading.spec.js
  • packages/venia-ui/lib/components/MiniCart/__tests__/productList.spec.js
  • packages/pagebuilder/lib/ContentTypes/Text/__tests__/text.spec.js
  • packages/venia-ui/lib/components/ForgotPassword/FormSubmissionSuccessful/__tests__/formSubmissionSuccessful.spec.js
  • packages/venia-ui/lib/components/CartPage/ProductListing/EditModal/__tests__/productDetail.spec.js
  • packages/venia-ui/lib/components/CartPage/PriceAdjustments/GiftOptions/__tests__/giftOptions.spec.js
  • packages/pagebuilder/lib/ContentTypes/Divider/__tests__/divider.spec.js
  • packages/venia-ui/lib/components/MiniCart/__tests__/body.spec.js
  • packages/venia-ui/lib/components/SearchBar/__tests__/autocomplete.spec.js
  • packages/venia-ui/lib/components/CategoryTree/__tests__/categoryBranch.spec.js
  • packages/pagebuilder/lib/ContentTypes/Html/__tests__/html.spec.js
  • packages/venia-ui/lib/components/ProductOptions/__tests__/options.spec.js
  • packages/venia-ui/lib/components/Accordion/__tests__/accordion.spec.js
  • packages/venia-ui/lib/components/CartPage/ProductListing/__tests__/quantity.spec.js
  • packages/venia-ui/lib/components/ButtonGroup/__tests__/buttonGroup.spec.js
  • packages/peregrine/lib/talons/Accordion/__tests__/useAccordion.spec.js
  • packages/venia-ui/lib/components/SearchBar/__tests__/suggestedProduct.spec.js
  • packages/venia-ui/lib/util/__tests__/images.spec.js
  • packages/venia-ui/lib/components/RichContent/__tests__/richContent.spec.js
  • packages/venia-ui/lib/components/Image/___tests__/simpleImage.spec.js
  • packages/venia-ui/lib/components/Checkout/Receipt/__tests__/receipt.spec.js
  • packages/venia-ui/lib/components/ForgotPassword/ForgotPasswordForm/__tests__/forgotPasswordForm.spec.js
  • packages/peregrine/lib/talons/CartPage/GiftCards/__tests__/useGiftCard.spec.js
  • packages/venia-ui/lib/components/MiniCart/__tests__/totalsSummary.spec.js
  • packages/pagebuilder/lib/ContentTypes/ColumnGroup/__tests__/columnGroup.spec.js
  • packages/venia-ui/lib/components/MiniCart/__tests__/kebab.spec.js
  • packages/venia-ui/lib/components/CartPage/PriceAdjustments/__tests__/priceAdjustments.spec.js
  • packages/venia-ui/lib/components/CategorySort/__tests__/categorySort.spec.js
  • packages/venia-ui/lib/components/CmsBlock/__tests__/block.spec.js
  • packages/venia-ui/lib/components/MiniCart/__tests__/footer.spec.js
🚫

GraphQL queries did not pass. Make sure to execute yarn run validate-queries locally prior to committing.

🚫

Unable to build scaffolded project.

yarn build

within a scaffolded project directory failed.
Learn more about Scaffolding at https://magento.github.io/pwa-studio/pwa-buildpack/scaffolding/.

🚫 A version label is required. A maintainer must add one.
🚫

node` failed.

Messages
📖

Access a deployed version of this PR here. Make sure to wait for the "pwa-pull-request-deploy" job to complete.

📖 DangerCI Failures related to missing labels/description/linked issues/etc will persist until the next push or next nightly build run (assuming they are fixed).

Log

ERROR ON TASK: prettierCheck


ERROR ON TASK: unitTests


ERROR ON TASK: validateQueries


ERROR ON TASK: scaffoldingSucceeds


Error:  Danger had errors running. See message(s) above for more details.
danger-results://tmp/danger-results.json

Generated by 🚫 dangerJS against eaa7235

Lint and prettier fixes
Small code improvements
@loid345
Copy link

loid345 commented Apr 19, 2020

Will this implementation support multisite?

@zetlen
Copy link
Contributor

zetlen commented Jun 14, 2020

@chris-brabender First, I'm terribly sorry. Two months is a ridiculously long wait for such a generous contributions. Mea culpa; this really fell to me to start the review, and I spent the last two months too focused on extensibility drafts to give you good feedback.

I'll start a review now--this comment is just to let you know that I've started.

Copy link
Contributor

@zetlen zetlen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much. It was fun to go over this, and it took a while to set it all up and demo to myself, but that was my own fault.

This set of comments is just a start; I'm ready to have a meeting with you and @tjwiebell and @jimbo to go over the next steps for this. But here's what I think they would be.

  1. Address the big questions here about suspense and inlining of query responses
  2. Rebase this PR on develop to get access to targets
  3. Brainstorm what targets you could use today to integrate this
  4. For the missing pieces or the hard parts, request or implement the targets that would make things easier (e.g. for adding cache invalidation rules to useQuery)
  5. Eventually, refactor this as an extension and go to Disneyland (when it's open again I guess)

Once again, thanks. I'll follow up with y'all through other channels.

Comment on lines +104 to +108
],
"dependencies": {
"i18next": "~19.1.0",
"react-i18next": "~11.3.3"
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this belongs in devDependencies. The root repository isn't a production repo--the closest it comes to prod is that it's often used in deploys.

Comment on lines +8 to +15

/** Get and Set current store view */
if (typeof persistence.getItem('store_view') === 'undefined' || typeof persistence.getItem('locale') === 'undefined') {
persistence.setItem('store_view', DEFAULT_STORE_VIEW.code);
persistence.setItem('locale', DEFAULT_STORE_VIEW.locale);
}

const routeCacheKey = 'urlResolver_' + persistence.getItem('store_view');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That you have to do this tells me that we need this type of store state in a top-level ContextProvider. Did you try, at one point, to do this using React state patterns and found no place to put it? That's a missing feature in Peregrine, if so. Seems like the sensible place for it to go is a slice in the Redux store, for now. @jimbo might say that the app slice is for UI state and not content state, though, so if the team thinks app isn't appropriate, then we'd put it in something else. Maybe a ContextProvider and a reducer hook, instead of Redux.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I think the recommendation from you / the team was to steer away from ContextProviders. I did review it initially but did not in the end go with it because the context providers are added after the first call we need to the localisation service.

@@ -89,17 +96,33 @@ function remotelyResolveRoute(opts) {
* @returns {Promise<{type: "PRODUCT" | "CATEGORY" | "CMS_PAGE"}>}
*/
function fetchRoute(opts) {
// String lang path from url resolver
const availableStoreViews = AVAILABLE_STORE_VIEWS;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The webpack.DefinePlugin will inline the object literal here and everywhere else this string goes. It's probably not a large object, but it'll bloat the bundle unless it's centralized in a constants module somewhere--plus, in a place like this, the whole object gets reallocated every time fetchRoute() is called.

route = route.substring(path.length, route.length);
}
});
route = route === '' ? '/' : route;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wasn't working for me when I set up separate store views for French and Spanish. I tried it both with the "store views in URL path" options set and without. This may partly be a bug in urlResolver, but at any rate I'd like to know if/how you plan to support both use cases, with store view URLs turned on and without.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now the match is on the en_us pattern, so if you had just /fr or /es or /fr_FR it may not have worked properly.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we could retrieve the paths from system config but that data isn't available via GraphQL for now.

Comment on lines +28 to +30
const _t = useCallback(phrase => {
return i18n.t(phrase);
}, []);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[deep breath]

This branch adds react-i18next as a dependency, but I don't see it in use anywhere. Were you using it at some point? If I remember right, you knew about react-i18next's useTranslation hook but chose to use the i18n client directly.

In your implementation, components retrieve translated text from this useLocalization hook. You could call useTranslation in this hook to get the _t function out, but instead you're just pulling the function from the i18n singleton. This is simple, but it prevents you from using the asynchronous-load feature of the useTranslation hook.

I know that this PR inlines all of the translations and therefore doesn't need to suspend to get them, but we know that that won't scale to large translation dictionaries. If we know we have to change the signature of useLocalization from sync to async eventually, let's do it now. Let's switch to useTranslation and do the refactoring work to make all the localized components deal with it a possible suspense properly. (We'll probably have to do this soon anyway.)

Comment on lines +53 to +79
const getTranslations = (local, phrases) => {
const variables = { locale: local, phrases: phrases };
const query = graphQLQueries.getTranslations;
return fetchQuery(JSON.stringify({ query, variables })).then(
data => data.translate.items
);
};

/**
* Get Available Locales
*/
const getAvailableLocales = () => {
const query = graphQLQueries.getAvailableLocales;
return fetchQuery(JSON.stringify({ query })).then(
data => data.availableLocales.items
);
};

/**
* Get Available Store Views
*/
const getAvailableStoreViews = () => {
console.log('Fetching available store views');
const query = graphQLQueries.getAvailableStoreViews;
return fetchQuery(JSON.stringify({ query })).then(
data => data.availableStoreViews.items
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shows a clear intention to hardcode the available translations and store views into the bundle. It's fast and simple, but it does mean that all that data gets locked in at build time and can't change without a rebuild.

I know we discussed this extensively in other channels. Now that I see it written out, I think there's a clear use case for a Webpack plugin here which preloads query results at build time in a way that the client app can still fetch the results with useQuery. With parameterized queries, that's a little harder, but most of these queries have no dependencies on an app context. It would be interesting to think about a general case for GraphQL prefetch at build time.

(I know this kinda turns into a circular dependency at build time, or a zig-zag dependency graph where production depends on staging, etc. It's still obviously the right thing to do in some cases, and I'm glad you did it.)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see translations changing without deployments when working with traditional magento sites to be honest. I don't think we neeed to be able to fetch this dynamically. But we can explore options. The issue is loading up a page where the language is supposed to be set (say when entering a route specifically) and having an english block shown while it is still fetching a french/spanish translation.

Comment on lines +9 to +20
module.exports.command = 'parse-translations <directory>';

module.exports.describe =
'Load and validate the current environment, including .env file if present, to ensure all required configuration is in place.';

module.exports.builder = {
coreDevMode: {
type: 'boolean',
desc:
'For core @magento/pwa-studio repository development. Creates a .env file populated with examples if one is not present.'
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know you left these in when copying another CLI as a template, but it still threw me for a loop.

Comment on lines +112 to +114
results.forEach(function(result) {
parser.parseFuncFromString(fs.readFileSync(result), { list: ['_t'] });
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brilliant! This is a beautiful feature of i18next used very well. While I appreciate you making a new Buildpack command (really, this is the first one I've seen, and it's great), I wonder if this could be done as a target integration with the Webpack compiler.

Webpack parser hooks let you take advantage of the parse that Webpack already does. The https://github.com/Perlmint/ya-i18next-webpack-plugin uses that feature; I forget if we discussed this plugin already. It would be great to automatically gather (and aggressively cache) these translations as part of a normal build, rather than as a separate command to remember to run.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that plugin has been brought up before as I was more looking at react i18n rather than webpack. But looks good initially.

Comment on lines +2 to +11
query {
availableStoreViews {
items {
code
name
locale
is_default
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your PR to Magento 2 didn't have this in the schema, but I was able to mock it out fine.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was a second PR for this I thought, one for StoreConfig and one for Translations. The second one should have had this in it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like that PR never got submitted. My bad.

Comment on lines +14 to +18
* Merge Venia UI and Local Resources together
* We can add additional resources here (maybe from peregrine for example)
* Would want to look at exposing this to the extensibility work also
*/
const resources = merge(resourcesVeniaUI, resourcesLocal);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! We absolutely want to merge and override here. Seems like the pattern here is already most of the way there; you've got a loader which renders this data as JSON, and you could change it to codegen which yields the JSON directly. To match a pattern which we've used elsewhere:

  1. Replace the two calls to Venia and local with a single call: import resources from '@absolunet/pwa-i18n/magic-resources' or something.
  2. Implement magic-resources to assemble the localization files in all dependencies
  3. Use the new transformModules Target to apply a val-loader to that file only

You could call your own targets in there, exposing your own localization extension points.
4.

@larsroettig
Copy link
Member

Should be closed because is already totally different implemented and can not merge and makes no sense to merge this

@larsroettig larsroettig closed this Oct 2, 2020
@tjwiebell
Copy link
Contributor

@magento assign extra credits to @chris-brabender for leading the design and research on i18n implementation: 80 points

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants