From f17883e32a1392080aae63d06f532d974e7754f5 Mon Sep 17 00:00:00 2001 From: Weizheng Gao <44440575+WeizhengSap@users.noreply.github.com> Date: Mon, 29 Jul 2019 09:13:32 -0400 Subject: [PATCH] Feature/gh 3736 (#3748) * feature/GH-3736: add script for localization process --- lang/properties/dummy.txt | 0 package.json | 2 + .../assets/src/translations/translations.ts | 2 + .../assets/src/translations/zh/address.ts | 56 ++++++++++ projects/assets/src/translations/zh/cart.ts | 28 +++++ .../assets/src/translations/zh/checkout.ts | 46 ++++++++ projects/assets/src/translations/zh/common.ts | 100 ++++++++++++++++++ projects/assets/src/translations/zh/index.ts | 23 ++++ .../assets/src/translations/zh/my-account.ts | 99 +++++++++++++++++ .../assets/src/translations/zh/payment.ts | 38 +++++++ .../assets/src/translations/zh/product.ts | 68 ++++++++++++ projects/assets/src/translations/zh/pwa.ts | 10 ++ .../src/translations/zh/store-finder.ts | 21 ++++ projects/assets/src/translations/zh/user.ts | 70 ++++++++++++ scripts/generate-jsons.ts | 72 +++++++++++++ scripts/generate-properties.ts | 41 +++++++ 16 files changed, 676 insertions(+) create mode 100644 lang/properties/dummy.txt create mode 100644 projects/assets/src/translations/zh/address.ts create mode 100644 projects/assets/src/translations/zh/cart.ts create mode 100644 projects/assets/src/translations/zh/checkout.ts create mode 100644 projects/assets/src/translations/zh/common.ts create mode 100644 projects/assets/src/translations/zh/index.ts create mode 100644 projects/assets/src/translations/zh/my-account.ts create mode 100644 projects/assets/src/translations/zh/payment.ts create mode 100644 projects/assets/src/translations/zh/product.ts create mode 100644 projects/assets/src/translations/zh/pwa.ts create mode 100644 projects/assets/src/translations/zh/store-finder.ts create mode 100644 projects/assets/src/translations/zh/user.ts create mode 100644 scripts/generate-jsons.ts create mode 100644 scripts/generate-properties.ts diff --git a/lang/properties/dummy.txt b/lang/properties/dummy.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/package.json b/package.json index 180549df021..7e14dca350c 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,8 @@ "generate:changelog": "ts-node ./scripts/changelog.ts", "generate:docs": "npx compodoc -p tsconfig.compodoc.json && ./scripts/zip-docs.sh", "generate:translations": "ts-node ./scripts/generate-translations", + "generate:localization:properties": "ts-node ./scripts/generate-properties", + "generate:localization:jsons": "ts-node ./scripts/generate-jsons && prettier './projects/assets/src/translations/**/*.ts' --write", "lint": "ng lint", "i18n-lint": "i18n-lint -t \"{{,}}\" projects/storefrontlib/src/**/*.html", "mockserver": "cd ./projects/backend/mockgenerator && npm run start", diff --git a/projects/assets/src/translations/translations.ts b/projects/assets/src/translations/translations.ts index c02d44d37f4..3aaf17bbd41 100644 --- a/projects/assets/src/translations/translations.ts +++ b/projects/assets/src/translations/translations.ts @@ -1,4 +1,5 @@ import { en } from './en/index'; +import { zh } from './zh/index'; interface TranslationResources { [lang: string]: { @@ -10,4 +11,5 @@ interface TranslationResources { export const translations: TranslationResources = { en, + zh, }; diff --git a/projects/assets/src/translations/zh/address.ts b/projects/assets/src/translations/zh/address.ts new file mode 100644 index 00000000000..0cf191203ec --- /dev/null +++ b/projects/assets/src/translations/zh/address.ts @@ -0,0 +1,56 @@ +export const address = { + addressForm: { + title: 'Title', + firstName: { + label: 'First name', + placeholder: 'First Name', + }, + lastName: { + label: 'Last name', + placeholder: 'Last Name', + }, + address1: 'Address 1', + address2: 'Address 2 (optional)', + country: 'Country', + city: { + label: 'City', + placeholder: 'City', + }, + state: 'State', + zipCode: { + label: 'Zip code', + placeholder: 'Postal Code/Zip', + }, + phoneNumber: { + label: 'Phone number (optional)', + placeholder: '(555) 555 - 0123', + }, + saveAsDefault: 'Save as default', + chooseAddress: 'Choose address', + streetAddress: 'Street Address', + aptSuite: 'Apt, Suite', + selectOne: 'Select One...', + setAsDefault: 'Set as default', + titleRequired: 'Title is required.', + userAddressAddSuccess: 'New address was added successfully!', + userAddressUpdateSuccess: 'Address updated successfully!', + userAddressDeleteSuccess: 'Address deleted successfully!', + invalidAddress: 'Invalid Address', + }, + addressBook: { + addNewShippingAddress: 'Add a new shipping address', + editShippingAddress: 'Edit shipping address', + areYouSureToDeleteAddress: 'Are you sure you want to delete this address?', + addNewAddress: 'Add new address', + addAddress: 'Add address', + updateAddress: 'Update address', + backToAddressList: 'Back to address list', + }, + addressCard: { + default: 'DEFAULT', + selected: 'Selected', + setAsDefault: 'Set as default', + shipTo: 'Ship To', + billTo: 'Bill To', + }, +}; diff --git a/projects/assets/src/translations/zh/cart.ts b/projects/assets/src/translations/zh/cart.ts new file mode 100644 index 00000000000..cb3ea858314 --- /dev/null +++ b/projects/assets/src/translations/zh/cart.ts @@ -0,0 +1,28 @@ +export const cart = { + cartDetails: { + id: 'ID', + proceedToCheckout: 'Proceed to Checkout', + cartName: 'Cart #{{code}}', + }, + cartItems: { + id: 'ID', + description: 'Description', + item: 'Item', + itemPrice: 'Item price', + quantity: 'Qty', + quantityTitle: + 'The quantity represents the total number of this item in your cart.', + total: 'Total', + cartTotal: 'Cart total ({{count}} item)', + cartTotal_plural: 'Cart total ({{count}} items)', + }, + orderCost: { + orderSummary: 'Order Summary', + subtotal: 'Subtotal after discounts:', + estimatedShipping: 'Estimated shipping:', + discount: 'You saved:', + salesTax: 'Sales Tax:', + grossTax: 'The order total does not include tax of', + total: 'Total:', + }, +}; diff --git a/projects/assets/src/translations/zh/checkout.ts b/projects/assets/src/translations/zh/checkout.ts new file mode 100644 index 00000000000..d566d5d7ac8 --- /dev/null +++ b/projects/assets/src/translations/zh/checkout.ts @@ -0,0 +1,46 @@ +export const checkout = { + checkoutAddress: { + shippingAddress: 'Shipping Address', + selectYourShippingAddress: 'Select your Shipping Address', + defaultShippingAddress: 'Default Shipping Address', + verifyYourAddress: 'Verify your address', + ensureAccuracySuggestChange: + 'To ensure delivery accuracy, we suggest the change selected below.', + chooseAddressToUse: 'Please choose which address you would like to use:', + suggestedAddress: 'Suggested address', + enteredAddress: 'Entered address', + addNewAddress: 'Add New Address', + shipToThisAddress: 'Ship to this address', + editAddress: 'Edit address', + saveAddress: 'Save address', + }, + checkoutOrderConfirmation: { + confirmationOfOrder: 'Confirmation of Order:', + thankYou: 'Thank you for your order!', + invoiceHasBeenSentByEmail: + 'An invoice has been sent by email. You should receive it soon.', + orderItems: 'Order Items', + orderPlacedSuccessfully: 'Order placed successfully', + }, + checkoutReview: { + review: 'Review', + orderItems: 'Order Items', + confirmThatRead: 'I am confirming that I have read and agreed with the', + placeOrder: 'Place Order', + termsAndConditions: 'Terms & Conditions', + }, + checkoutShipping: { + shippingMethod: 'Shipping Method', + standardDelivery: 'Standard Delivery', + premiumDelivery: 'Premium Delivery', + }, + checkout: { + backToCart: 'Back to cart', + }, + checkoutProgress: { + shippingAddress: 'Shipping Address', + deliveryMode: 'Delivery mode', + paymentDetails: 'Payment details', + reviewOrder: 'Review order', + }, +}; diff --git a/projects/assets/src/translations/zh/common.ts b/projects/assets/src/translations/zh/common.ts new file mode 100644 index 00000000000..db3056ea022 --- /dev/null +++ b/projects/assets/src/translations/zh/common.ts @@ -0,0 +1,100 @@ +export const common = { + common: { + cancel: 'Cancel', + delete: 'Delete', + remove: 'Remove', + edit: 'Edit', + back: 'Back', + submit: 'Submit', + continue: 'Continue', + save: 'Save', + done: 'Done', + home: 'Home', + }, + pageMetaResolver: { + category: { + title: '{{count}} result for {{query}}', + title_plural: '{{count}} results for {{query}}', + }, + checkout: { + title: 'Checkout {{count}} item', + title_plural: 'Checkout {{count}} items', + }, + search: { + title: '{{count}} result for "{{query}}"', + title_plural: '{{count}} results for "{{query}}"', + }, + product: { + description: '{{description}}', + heading: '{{heading}}', + title: '{{title}}', + }, + }, + spinner: { + loading: 'Loading...', + }, + navigation: { + shopAll: 'Shop all {{ navNode}} >', + }, + searchBox: { + placeholder: 'Search here...', + help: { + insufficientChars: 'Please type more characters', + noMatch: 'We could not find any results', + exactMatch: '{{ term }}', + empty: 'Ask us anything', + }, + }, + sorting: { + date: 'Date', + orderNumber: 'Order Number', + }, + httpHandlers: { + badGateway: 'A server error occurred. Please try again later.', + badRequestPleaseLoginAgain: '{{ errorMessage }}. Please login again.', + badRequestOldPasswordIncorrect: 'Old password incorrect.', + conflict: 'Already exists', + forbidden: 'You are not authorized to perform this action.', + gatewayTimeout: 'The server did not responded, please try again later.', + unknownError: 'An unknown error occurred', + validationErrors: { + missing: { + card_cardType: + 'The credit card selected is not supported. Please select another.', + card_accountNumber: 'The credit card number entered is not valid.', + card_cvNumber: 'The security code entered is not valid.', + card_expirationMonth: + 'The credit card expiration date entered is not valid.', + card_expirationYear: + 'The credit card expiration date entered is not valid.', + billTo_firstName: 'The first name entered is not valid.', + billTo_lastName: 'The last name entered is not valid.', + billTo_street1: 'The address entered is not valid.', + billTo_street2: 'The address entered is not valid.', + billTo_city: 'The city entered is not valid for this credit card.', + billTo_state: + 'The state/province entered is not valid for this credit card.', + billTo_country: + 'The country entered is not valid for this credit card.', + billTo_postalCode: + 'The zip/postal code is not valid for this credit card.', + country: { + isocode: 'Missing country', + }, + }, + invalid: { + card_expirationMonth: + 'The credit card expiration date entered is not valid.', + }, + }, + cartNotFound: 'Cart not found.', + }, + miniCart: { + item: '{{count}} item currently in your cart', + item_plural: '{{count}} items currently in your cart', + }, + miniLogin: { + userGreeting: 'Hi, {{name}}', + signInRegister: 'Sign In / Register', + }, +}; diff --git a/projects/assets/src/translations/zh/index.ts b/projects/assets/src/translations/zh/index.ts new file mode 100644 index 00000000000..269b137e390 --- /dev/null +++ b/projects/assets/src/translations/zh/index.ts @@ -0,0 +1,23 @@ +import { cart } from './cart'; +import { checkout } from './checkout'; +import { common } from './common'; +import { myAccount } from './my-account'; +import { product } from './product'; +import { pwa } from './pwa'; +import { storeFinder } from './store-finder'; +import { user } from './user'; +import { payment } from './payment'; +import { address } from './address'; + +export const zh = { + address, + cart, + checkout, + common, + myAccount, + payment, + product, + pwa, + storeFinder, + user, +}; diff --git a/projects/assets/src/translations/zh/my-account.ts b/projects/assets/src/translations/zh/my-account.ts new file mode 100644 index 00000000000..38355e928a2 --- /dev/null +++ b/projects/assets/src/translations/zh/my-account.ts @@ -0,0 +1,99 @@ +export const myAccount = { + orderDetails: { + orderId: 'Order #', + placed: 'Placed', + status: 'Status', + shippedOn: 'Shipped on', + inProcess: 'In process...', + pending: 'Pending', + deliveryStatus_READY_FOR_PICKUP: 'Ready for pickup', + deliveryStatus_PICKUP_COMPLETE: 'Picked up', + deliveryStatus_SHIPPED: 'Shipped', + deliveryStatus_CANCELLED: 'Cancelled', + statusDisplay_cancelled: 'Cancelled', + statusDisplay_cancelling: 'Cancel Pending', + statusDisplay_completed: 'Completed', + statusDisplay_created: 'Created', + statusDisplay_error: 'Pending', + statusDisplay_Error: 'Pending', + statusDisplay_open: 'Open', + statusDisplay_processing: 'In Process', + }, + orderHistory: { + orderHistory: 'Order history', + orderId: 'Order #', + date: 'Date', + status: 'Status', + total: 'Total', + noOrders: 'We have no order records for this account.', + startShopping: 'Start Shopping', + sortByMostRecent: 'Sort by Most recent', + }, + closeAccount: { + confirmAccountClosure: 'Confirm Account Closure', + confirmAccountClosureMessage: + 'Are you sure you want to close your account?', + closeMyAccount: 'CLOSE MY ACCOUNT', + accountClosedSuccessfully: 'Account closed with success', + }, + updateEmailForm: { + newEmailAddress: { + label: 'New email address', + placeholder: 'Enter email', + }, + confirmNewEmailAddress: { + label: 'Confirm new email address', + placeholder: 'Enter email', + }, + enterValidEmail: 'Please enter a valid email.', + bothEmailMustMatch: 'Both emails must match', + password: { + label: 'Password', + placeholder: 'Enter password', + }, + pleaseInputPassword: 'Please input password', + emailUpdateSuccess: 'Success. Please sign in with {{ newUid }}', + }, + updatePasswordForm: { + oldPassword: { + label: 'Old Password', + placeholder: 'Old Password', + }, + oldPasswordIsRequired: 'Old password is required.', + newPassword: { + label: 'New Password', + placeholder: 'New Password', + }, + passwordMinRequirements: + 'Password must be six characters minimum, with one uppercase letter, one number, one symbol', + confirmPassword: { + label: 'Confirm New Password', + placeholder: 'Confirm Password', + }, + bothPasswordMustMatch: 'Both password must match', + passwordUpdateSuccess: 'Password updated with success', + }, + updateProfileForm: { + title: '', + none: '', + firstName: { + label: 'First name', + placeholder: 'First name', + }, + firstNameIsRequired: 'First name is required.', + lastName: { + label: 'Last name', + placeholder: 'Last name', + }, + lastNameIsRequired: 'Last name is required.', + profileUpdateSuccess: 'Personal details successfully updated', + }, + consentManagementForm: { + message: { + success: { + given: 'Consent successfully given.', + withdrawn: 'Consent successfully withdrawn.', + }, + }, + }, +}; diff --git a/projects/assets/src/translations/zh/payment.ts b/projects/assets/src/translations/zh/payment.ts new file mode 100644 index 00000000000..4e975091aac --- /dev/null +++ b/projects/assets/src/translations/zh/payment.ts @@ -0,0 +1,38 @@ +export const payment = { + paymentForm: { + payment: 'Payment', + choosePaymentMethod: 'Choose a payment method', + paymentType: 'Payment Type', + accountHolderName: { + label: 'Account Holder Name', + placeholder: 'Account Holder Name', + }, + cardNumber: 'Card Number', + expirationDate: 'Expiration Date', + securityCode: 'Security code (CVV)', + securityCodeTitle: 'Card Verification Value', + saveAsDefault: 'Save as default', + setAsDefault: 'Set as default', + billingAddress: 'Billing address', + sameAsShippingAddress: 'Same as shipping address', + selectOne: 'Select One...', + monthMask: 'MM', + yearMask: 'YYYY', + useThisPayment: 'Use this payment', + addNewPayment: 'Add New Payment', + changePayment: 'Change Payment', + }, + paymentMethods: { + paymentMethods: 'Payment methods', + newPaymentMethodsAreAddedDuringCheckout: + 'New payment methods are added during checkout.', + invalidField: 'InvalidField: {{ field }}', + }, + paymentCard: { + deleteConfirmation: 'Are you sure you want to delete this payment method?', + setAsDefault: 'Set as default', + expires: 'Expires: {{ month }}/{{ year }}', + defaultPaymentMethod: 'Default Payment Method', + selected: 'Selected', + }, +}; diff --git a/projects/assets/src/translations/zh/product.ts b/projects/assets/src/translations/zh/product.ts new file mode 100644 index 00000000000..d66280abf77 --- /dev/null +++ b/projects/assets/src/translations/zh/product.ts @@ -0,0 +1,68 @@ +export const product = { + productDetails: { + id: 'ID', + quantity: 'Qty', + productDetails: 'Product Details', + specification: 'Specs', + reviews: 'Reviews', + shipping: 'Shipping', + share: 'Share', + showReviews: 'Show reviews', + }, + productList: { + filterBy: { + label: 'Filter by', + action: 'Filter by', + }, + appliedFilter: 'Applied Filter:', + showLess: 'Show less...', + showMore: 'Show more...', + sortByRelevance: 'Sort by Relevance', + }, + productFacetNavigation: { + filterBy: { + label: 'Filter by', + action: 'Filter by', + }, + appliedFilter: 'Applied Filter:', + showLess: 'Show less...', + showMore: 'Show more...', + sortByRelevance: 'Sort by Relevance', + }, + productSummary: { + id: 'ID', + showReviews: 'Show reviews', + share: 'Share', + }, + productReview: { + overallRating: 'Overall Rating', + reviewTitle: 'Review Title', + writeYourComments: 'Write your comments', + rating: 'Rating', + reviewerName: 'Reviewer name (optional)', + writeReview: 'Write a Review', + more: 'More', + less: 'Less', + }, + addToCart: { + itemsAddedToYourCart: 'Item(s) added to your cart', + itemsIncrementedInYourCart: + 'This item was already in your cart. The quantity was updated.', + items: 'items', + updatingCart: 'Updating cart...', + addToCart: 'Add to cart', + viewCart: 'view cart', + proceedToCheckout: 'proceed to checkout', + quantity: 'Qty', + outOfStock: 'Out of stock', + inStock: 'In stock', + }, + CMSTabParagraphContainer: { + tabs: { + ProductDetailsTabComponent: 'Product Details', + ProductSpecsTabComponent: 'Specs', + ProductReviewsTabComponent: 'Reviews', + deliveryTab: 'Shipping', + }, + }, +}; diff --git a/projects/assets/src/translations/zh/pwa.ts b/projects/assets/src/translations/zh/pwa.ts new file mode 100644 index 00000000000..33ea0194cdd --- /dev/null +++ b/projects/assets/src/translations/zh/pwa.ts @@ -0,0 +1,10 @@ +export const pwa = { + pwa: { + addToHomeScreenDescription: + 'Add SAP storefront to your device homescreen for a faster return visit', + noInstallationNeeded: 'No installation needed', + fastAccessToApplication: 'Fast access to application', + addToHomeScreen: 'Add to home screen', + addedToHomeScreen: 'SAP Storefront was added to your home screen', + }, +}; diff --git a/projects/assets/src/translations/zh/store-finder.ts b/projects/assets/src/translations/zh/store-finder.ts new file mode 100644 index 00000000000..221a7865bef --- /dev/null +++ b/projects/assets/src/translations/zh/store-finder.ts @@ -0,0 +1,21 @@ +export const storeFinder = { + storeFinder: { + openUntil: 'Open until', + closed: 'Closed', + call: 'Call', + getDirections: 'Get Directions', + listView: 'List View', + mapView: 'Map View', + noStoresFound: 'No Stores Found.', + storeHours: 'Store hours', + storeFeatures: 'Store features', + fromStoresFound: 'from {{ count }} store found', + fromStoresFound_plural: 'from {{ count }} stores found', + findStore: 'Find store', + useMyLocation: 'Use my location', + viewAllStores: 'View all stores', + contactUs: 'Contact us', + searchBox: 'Enter postal code, town or address', + backToList: 'Back to list', + }, +}; diff --git a/projects/assets/src/translations/zh/user.ts b/projects/assets/src/translations/zh/user.ts new file mode 100644 index 00000000000..dd7b44448c9 --- /dev/null +++ b/projects/assets/src/translations/zh/user.ts @@ -0,0 +1,70 @@ +export const user = { + forgottenPassword: { + resetPassword: 'Reset password', + enterEmailAddressAssociatedWithYourAccount: + 'Enter the email address associated with your account', + emailAddress: { + label: 'Email address', + placeholder: 'Enter email', + }, + enterValidEmail: 'Please enter a valid email.', + passwordResetEmailSent: + 'An email has been sent to you with information on how to reset your password.', + passwordResetSuccess: 'Success! You can now login using your new password.', + }, + loginForm: { + forgotPassword: 'Forgot password?', + signIn: 'Sign In', + register: 'Register', + dontHaveAccount: 'Don’t have an account', + emailAddress: { + label: 'Email address', + placeholder: 'Enter email', + }, + password: { + label: 'Password', + placeholder: 'Password', + }, + wrongEmailFormat: 'This is not a valid email format.', + }, + register: { + confirmPassword: { + action: 'Confirm password', + label: 'Confirm password', + placeholder: 'Confirm Password', + }, + managmentInMyAccount: 'Management in My Account.', + termsAndConditions: 'Terms & Conditions', + signIn: 'I already have an account. Sign In', + register: 'Register', + confirmNewPassword: 'Confirm New Password', + resetPassword: 'Reset Password', + createAccount: 'Create an account', + title: 'Title', + firstName: { + label: 'First name', + placeholder: 'First name', + }, + lastName: { + label: 'Last name', + placeholder: 'Last name', + }, + emailAddress: { + label: 'Email address', + placeholder: 'Email address', + }, + password: { + label: 'Password', + placeholder: 'Password', + }, + newPassword: 'New Password', + emailMarketing: + 'Use my personal data to receive e-mail newsletters for marketing campaigns. To change your settings, go to Consent Management in My Account.', + confirmThatRead: 'I am confirming that I have read and agreed with the', + selectTitle: 'Select Title', + passwordMinRequirements: + 'Password must be six characters minimum, with one uppercase letter, one number, one symbol', + bothPasswordMustMatch: 'Both password must match', + titleRequired: 'Title is required.', + }, +}; diff --git a/scripts/generate-jsons.ts b/scripts/generate-jsons.ts new file mode 100644 index 00000000000..28e1184d584 --- /dev/null +++ b/scripts/generate-jsons.ts @@ -0,0 +1,72 @@ +import * as fs from 'fs-extra'; +import { translations } from '../projects/assets/src/translations/translations'; + +function propertiesToJson(properties) { + const jsonObj = {}; + properties.forEach(property => { + if (property.length > 0) { + const name = property.split('=')[0]; + const value = property.split('=')[1]; + const names = name.split('.'); + getJsonObj(names, value, jsonObj); + } + }); + + return jsonObj; +} + +function getJsonObj(names, value, jsonObj) { + const name = names[0]; + if (names.length === 1) { + jsonObj[name] = value; + } else { + jsonObj[name] = getJsonObj(names.slice(1), value, jsonObj[name] || {}); + } + return jsonObj; +} + +const jsons = new Map(); +const files = fs.readdirSync('./lang/properties'); +if (files) { + files.forEach(file => { + if (file.endsWith('.properties')) { + const path = './lang/properties/' + file; + const properties = fs.readFileSync(path, 'utf8').split('\n'); + const json = propertiesToJson(properties); + const key = file.substring(0, file.indexOf('.')); + jsons.set(key, json); + } + }); +} + +Object.keys(translations).forEach(lang => { + Object.keys(translations[lang]).forEach(chunk => { + const translated = jsons.get(chunk + '_' + lang); + if (translated) { + translations[lang][chunk] = translated; + } + }); + + const assetsTransPath = './projects/assets/src/translations'; + const tsFiles = fs.readdirSync(assetsTransPath + '/' + lang); + if (tsFiles) { + tsFiles.forEach(file => { + if (file !== 'index.ts') { + const path = assetsTransPath + '/' + lang + '/' + file; + const content = fs.readFileSync(path, 'utf8'); + const firstLine = content.split('=')[0]; + const chunk = firstLine + .trim() + .split(' ') + .pop(); + fs.writeFileSync( + path, + firstLine + '=' + JSON.stringify(translations[lang][chunk], null, 2), + 'utf8' + ); + } + }); + } +}); + +console.log(`properties files are converted to json files`); diff --git a/scripts/generate-properties.ts b/scripts/generate-properties.ts new file mode 100644 index 00000000000..a9e2796b9fe --- /dev/null +++ b/scripts/generate-properties.ts @@ -0,0 +1,41 @@ +import * as fs from 'fs-extra'; +import { translations } from '../projects/assets/src/translations/translations'; + +function writeProperties(dir, fileName, properties) { + const writeStream = fs.createWriteStream(dir + '/' + fileName, { + autoClose: false, + }); + properties.forEach(property => writeStream.write(property + '\n')); + writeStream.end(); +} + +function jsonToProperties(jsonObj, prefix?) { + let result = []; + Object.keys(jsonObj).forEach(key => { + let _prefix; + if (jsonObj[key] && typeof jsonObj[key] === 'object') { + const _currPrefix = key + '.'; + _prefix = prefix ? prefix + _currPrefix : _currPrefix; + result = [...result, ...jsonToProperties(jsonObj[key], _prefix)]; + } else { + _prefix = prefix ? prefix + key : key; + result.push(_prefix + '=' + jsonObj[key] || ''); + } + }); + return result; +} + +// generate properties files +Object.keys(translations).forEach(lang => { + Object.keys(translations[lang]).forEach(chunk => { + const obj = translations[lang][chunk]; + const json = JSON.stringify(obj, null, 2); + const properties = jsonToProperties(JSON.parse(json)); + writeProperties( + './lang/properties', + chunk + '_' + lang + '.properties', + properties + ); + }); +}); +console.log(`localized properties files are generated`);