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

Add i18n support #848

Draft
wants to merge 34 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
e4de983
feat: add i18n helper and provider
pfferrari Dec 11, 2024
2351b3f
feat: add i18n-locales package
pfferrari Dec 11, 2024
39f57fe
chore: export useTranslation
marcomontalbano Dec 11, 2024
4c6d87d
perf: import useTranslation from app-elements in docs
pfferrari Dec 11, 2024
546d416
chore: rename localeUrl prop
pfferrari Dec 11, 2024
584f4bd
feat: add translations for dictionaries
pfferrari Dec 12, 2024
bb31bdd
fix: remove i18n package to ship locales with app-elements using `i18…
gciotola Dec 13, 2024
310c083
fix: remove `useTranslation` in functions (non-react components)
gciotola Dec 13, 2024
b2a36d0
feat: add translations for hooks
pfferrari Dec 16, 2024
a59be3f
fix: use `ts` file to improve type definitions in consumer apps
gciotola Dec 16, 2024
1b2c50b
fix: update vite plugin hook
gciotola Dec 16, 2024
92faaad
fix: apply new structure to locales
gciotola Dec 16, 2024
759e87c
Merge branch 'add-i18n-typescript' into add-i18n
gciotola Dec 16, 2024
f08f848
fix: add static type defs for locales
gciotola Dec 16, 2024
675eabd
fix: add more keys for app-orders
gciotola Dec 17, 2024
a909df0
fix: add new locale keys
gciotola Dec 17, 2024
90fdefe
fix: update locales import path
gciotola Dec 17, 2024
9913a25
feat: add locales for composite components
pfferrari Dec 18, 2024
db10b94
fix: reorganize empty states locale keys
gciotola Dec 18, 2024
255ab19
chore: add new locales for forms components
pfferrari Dec 18, 2024
20aa4e3
fix: add new keys for app orders and links
gciotola Dec 18, 2024
a79d105
fix: update translations for app orders
gciotola Dec 18, 2024
809bd7f
chore: add locales for forms components
pfferrari Dec 18, 2024
d2773f7
feat: add locales for resources components
pfferrari Dec 19, 2024
db6926b
fix: add new translations keys for app customers
gciotola Dec 19, 2024
ad44ccd
fix: add more keys of app-customers
gciotola Dec 19, 2024
7beac90
fix: improve loading state in i18n provider
gciotola Dec 19, 2024
3cb6e43
fix: add missing translations for app shipments
gciotola Dec 20, 2024
a10a4d7
chore: add locales for resources components
pfferrari Dec 20, 2024
11b33dc
fix: export Trans component
gciotola Dec 20, 2024
c3ee0dd
fix: update locales for orders and returns
gciotola Dec 20, 2024
2119279
fix: add missing locale keys
gciotola Dec 20, 2024
0bb1d28
fix: update locale keys
gciotola Dec 20, 2024
481650d
fix: typos
gciotola Dec 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/app-elements/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@
"@types/react-datepicker": "^7.0.0",
"@types/react-dom": "^18.3.1",
"classnames": "^2.5.1",
"i18next": "^24.0.5",
"i18next-browser-languagedetector": "^8.0.0",
"i18next-resources-to-backend": "^1.2.1",
"js-cookie": "^3.0.5",
"jwt-decode": "^4.0.0",
"lodash": "^4.17.21",
Expand All @@ -55,6 +58,7 @@
"react-datepicker": "^7.5.0",
"react-dom": "^18.3.1",
"react-hook-form": "^7.53.2",
"react-i18next": "^15.1.3",
"react-select": "^5.8.3",
"react-tooltip": "^5.28.0",
"swr": "^2.2.5",
Expand Down
19 changes: 10 additions & 9 deletions packages/app-elements/src/dictionaries/customers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Customer } from '@commercelayer/sdk'
import { t } from 'i18next'
import type { DisplayStatus } from './types'

export interface CustomerDisplayStatus extends DisplayStatus {}
Expand All @@ -9,35 +10,35 @@ export function getCustomerDisplayStatus(
switch (customerObj.status) {
case 'prospect':
return {
label: 'Prospect',
label: t('resources.customers.attributes.status.prospect'),
icon: 'chatCircle',
color: 'orange',
task: 'Prospect'
task: t('resources.customers.attributes.status.prospect')
}

case 'acquired':
return {
label: 'Acquired',
label: t('resources.customers.attributes.status.acquired'),
icon: 'check',
color: 'orange',
task: 'Acquired'
task: t('resources.customers.attributes.status.acquired')
}

case 'repeat':
return {
label: 'Repeat',
label: t('resources.customers.attributes.status.repeat'),
icon: 'arrowUpRight',
color: 'orange',
task: 'Repeat'
task: t('resources.customers.attributes.status.repeat')
}
}
}

export function getCustomerStatusName(status: Customer['status']): string {
const dictionary: Record<typeof status, string> = {
prospect: 'Prospect',
acquired: 'Acquired',
repeat: 'Repeat'
prospect: t('resources.customers.attributes.status.prospect'),
acquired: t('resources.customers.attributes.status.acquired'),
repeat: t('resources.customers.attributes.status.repeat')
}

return dictionary[status]
Expand Down
121 changes: 71 additions & 50 deletions packages/app-elements/src/dictionaries/orders.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { StatusIconProps } from '#ui/atoms/StatusIcon'
import type { Order } from '@commercelayer/sdk'
import { t } from 'i18next'
import type { DisplayStatus } from './types'
export interface OrderDisplayStatus extends DisplayStatus {
label: string
Expand All @@ -14,10 +15,10 @@ export function getOrderDisplayStatus(order: Order): OrderDisplayStatus {

if (order.status === 'editing') {
return {
label: 'Editing',
label: t('resources.orders.attributes.status.editing'),
icon: 'pencilSimple',
color: 'orange',
task: 'Editing'
task: t('resources.orders.attributes.status.editing')
}
}

Expand All @@ -31,79 +32,81 @@ export function getOrderDisplayStatus(order: Order): OrderDisplayStatus {
case 'placed:free:unfulfilled':
case 'placed:free:not_required':
return {
label: 'Placed',
label: t('resources.orders.attributes.status.placed'),
icon: 'arrowDown',
color: 'orange',
task: 'Awaiting approval'
task: t('apps.orders.tasks.awaiting_approval')
}

case 'placed:unpaid:unfulfilled':
return {
label: 'Placed',
label: t('resources.orders.attributes.status.placed'),
icon: 'x',
color: 'red',
task: 'Error to cancel'
task: t('apps.orders.tasks.error_to_cancel')
}

case 'approved:authorized:unfulfilled':
case 'approved:authorized:not_required':
return {
label: 'Approved',
label: t('resources.orders.attributes.status.approved'),
icon: 'creditCard',
color: 'orange',
task: 'Payment to capture'
task: t('apps.orders.tasks.payment_to_capture')
}

case 'approved:paid:in_progress':
case 'approved:partially_refunded:in_progress':
return {
label: 'In progress',
label: t('apps.orders.display_status.in_progress'),
icon: 'arrowClockwise',
color: 'orange',
task: 'Fulfillment in progress'
task: t('apps.orders.tasks.fulfillment_in_progress')
}

case 'approved:authorized:in_progress':
return {
label: 'In progress (Manual)',
label: t('apps.orders.display_status.in_progress_manual'),
icon: 'arrowClockwise',
color: 'orange',
task: 'Fulfillment in progress'
task: t('apps.orders.tasks.fulfillment_in_progress')
}

case 'approved:paid:fulfilled':
return {
label: 'Fulfilled',
label: t('resources.orders.attributes.fulfillment_status.fulfilled'),
icon: 'check',
color: 'green'
}

// TODO: This could be a gift-card and what If i do return?
case 'approved:free:fulfilled':
return {
label: 'Fulfilled',
label: t('resources.orders.attributes.fulfillment_status.fulfilled'),
icon: 'check',
color: 'green'
}

case 'approved:paid:not_required':
case 'approved:partially_refunded:not_required':
return {
label: 'Approved',
label: t('resources.orders.attributes.status.approved'),
icon: 'check',
color: 'green'
}

case 'approved:free:not_required':
return {
label: 'Approved',
label: t('resources.orders.attributes.status.approved'),
icon: 'check',
color: 'green'
}

case 'approved:partially_refunded:fulfilled':
return {
label: 'Part. refunded',
label: t(
'resources.orders.attributes.payment_status.partially_refunded'
),
icon: 'check',
color: 'green'
}
Expand All @@ -114,14 +117,14 @@ export function getOrderDisplayStatus(order: Order): OrderDisplayStatus {
case 'cancelled:unpaid:unfulfilled':
case 'cancelled:free:unfulfilled':
return {
label: 'Cancelled',
label: t('resources.orders.attributes.status.cancelled'),
icon: 'x',
color: 'gray'
}

case 'cancelled:refunded:fulfilled':
return {
label: 'Cancelled',
label: t('resources.orders.attributes.status.cancelled'),
icon: 'x',
color: 'gray'
}
Expand All @@ -130,14 +133,14 @@ export function getOrderDisplayStatus(order: Order): OrderDisplayStatus {
case 'pending:authorized:unfulfilled':
case 'pending:free:unfulfilled':
return {
label: 'Pending',
label: t('resources.orders.attributes.status.pending'),
icon: 'shoppingBag',
color: 'white'
}

default:
return {
label: `Not handled: (${combinedStatus})`,
label: `${t('common.not_handled')}: (${combinedStatus})`,
icon: 'warning',
color: 'white'
}
Expand All @@ -148,16 +151,20 @@ export function getOrderTransactionName(
type: NonNullable<Order['transactions']>[number]['type']
): { pastTense: string; singular: string } {
const pastTenseDictionary: Record<typeof type, string> = {
authorizations: 'authorized',
captures: 'captured',
refunds: 'refunded',
voids: 'voided'
authorizations: t(
'resources.orders.attributes.payment_status.authorized'
).toLowerCase(),
captures: t('apps.orders.details.payment_captured').toLowerCase(),
refunds: t(
'resources.orders.attributes.payment_status.refunded'
).toLowerCase(),
voids: t('resources.orders.attributes.payment_status.voided').toLowerCase()
}
const singularDictionary: Record<typeof type, string> = {
authorizations: 'Payment authorization',
captures: 'Payment capture',
refunds: 'Refund',
voids: 'Void'
authorizations: t('apps.orders.details.payment_authorization'),
captures: t('apps.orders.details.payment_capture'),
refunds: t('apps.orders.details.payment_refund'),
voids: t('apps.orders.details.payment_void')
}

return {
Expand All @@ -168,13 +175,13 @@ export function getOrderTransactionName(

export function getOrderStatusName(status: Order['status']): string {
const dictionary: Record<typeof status, string> = {
approved: 'Approved',
cancelled: 'Cancelled',
draft: 'Draft',
editing: 'Editing',
pending: 'Pending',
placed: 'Placed',
placing: 'Placing'
approved: t('resources.orders.attributes.status.approved'),
cancelled: t('resources.orders.attributes.status.cancelled'),
draft: t('resources.orders.attributes.status.draft'),
editing: t('resources.orders.attributes.status.editing'),
pending: t('resources.orders.attributes.status.pending'),
placed: t('resources.orders.attributes.status.placed'),
placing: t('resources.orders.attributes.status.placing')
}

return dictionary[status]
Expand All @@ -184,16 +191,24 @@ export function getOrderPaymentStatusName(
status: Order['payment_status']
): string {
const dictionary: Record<typeof status, string> = {
authorized: 'Authorized',
paid: 'Paid',
unpaid: 'Unpaid',
free: 'Free',
voided: 'Voided',
refunded: 'Refunded',
partially_authorized: 'Part. authorized',
partially_paid: 'Part. paid',
partially_refunded: 'Part. refunded',
partially_voided: 'Part. voided'
authorized: t('resources.orders.attributes.payment_status.authorized'),
paid: t('resources.orders.attributes.payment_status.paid'),
unpaid: t('resources.orders.attributes.payment_status.unpaid'),
free: t('resources.orders.attributes.payment_status.free'),
voided: t('resources.orders.attributes.payment_status.voided'),
refunded: t('resources.orders.attributes.payment_status.refunded'),
partially_authorized: t(
'resources.orders.attributes.payment_status.partially_authorized'
),
partially_paid: t(
'resources.orders.attributes.payment_status.partially_paid'
),
partially_refunded: t(
'resources.orders.attributes.payment_status.partially_refunded'
),
partially_voided: t(
'resources.orders.attributes.payment_status.partially_voided'
)
}

return dictionary[status]
Expand All @@ -203,10 +218,16 @@ export function getOrderFulfillmentStatusName(
status: Order['fulfillment_status']
): string {
const dictionary: Record<typeof status, string> = {
unfulfilled: 'Unfulfilled',
in_progress: 'In progress',
fulfilled: 'Fulfilled',
not_required: 'Not required'
unfulfilled: t(
'resources.orders.attributes.fulfillment_status.unfulfilled'
),
in_progress: t(
'resources.orders.attributes.fulfillment_status.in_progress'
),
fulfilled: t('resources.orders.attributes.fulfillment_status.fulfilled'),
not_required: t(
'resources.orders.attributes.fulfillment_status.not_required'
)
}

return dictionary[status]
Expand Down
11 changes: 6 additions & 5 deletions packages/app-elements/src/dictionaries/promotions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { getEventDateInfo } from '#helpers/date'
import type { Promotion } from '@commercelayer/sdk'
import { t } from 'i18next'
import type { DisplayStatus } from './types'

interface PromotionDisplayStatus extends DisplayStatus {
Expand All @@ -12,7 +13,7 @@ export function getPromotionDisplayStatus(
if (promotion.disabled_at != null) {
return {
status: 'disabled',
label: 'Disabled',
label: t('resources.promotions.attributes.status.disabled'),
icon: 'minus',
color: 'lightGray'
}
Expand All @@ -29,7 +30,7 @@ export function getPromotionDisplayStatus(
) {
return {
status: 'used',
label: 'Expired',
label: t('resources.promotions.attributes.status.expired'),
icon: 'flag',
color: 'gray'
}
Expand All @@ -39,23 +40,23 @@ export function getPromotionDisplayStatus(
case 'past':
return {
status: 'expired',
label: 'Expired',
label: t('resources.promotions.attributes.status.expired'),
icon: 'flag',
color: 'gray'
}

case 'upcoming':
return {
status: 'upcoming',
label: 'Upcoming',
label: t('apps.promotions.display_status.upcoming'),
icon: 'calendarBlank',
color: 'gray'
}

case 'active':
return {
status: 'active',
label: 'Active',
label: t('resources.promotions.attributes.status.active'),
icon: 'pulse',
color: 'green'
}
Expand Down
Loading
Loading