diff --git a/README.md b/README.md index 4a5c78d..ab0201b 100644 --- a/README.md +++ b/README.md @@ -289,38 +289,36 @@ Default is [EN_US](https://github.com/bytescale/bytescale-upload-widget/blob/mai ```javascript const myCustomLocale = { - "error!": "Error!", - "done": "Done", - "addAnotherFile": "Add another file...", - "addAnotherImage": "Add another image...", - "cancel": "cancel", - "cancelInPreviewWindow": "Cancel", - "cancelled!": "cancelled", - "continue": "Continue", - "customValidationFailed": "Failed to validate file.", - "crop": "Crop", - "finish": "Finished", - "finishIcon": true, - "image": "Image", - "maxFilesReached": "Maximum number of files:", - "maxImagesReached": "Maximum number of images:", - "maxSize": "File size limit:", - "next": "Next", - "of": "of", - "orDragDropFile": "...or drag and drop a file.", - "orDragDropFiles": "...or drag and drop files.", - "orDragDropImage": "...or drag and drop an image.", - "orDragDropImages": "...or drag and drop images.", - "pleaseWait": "Please wait...", - "removed!": "removed", - "remove": "remove", - "skip": "Skip", - "unsupportedFileType": "File type not supported.", - "uploadFile": "Upload a File", - "uploadFiles": "Upload Files", - "uploadImage": "Upload an Image", - "uploadImages": "Upload Images", - "validatingFile": "Validating file..." + addAnotherFileBtn: "Add another file...", + addAnotherImageBtn: "Add another image...", + cancelBtn: "cancel", + cancelBtnClicked: "cancelled", + cancelPreviewBtn: "Cancel", + continueBtn: "Continue", + cropBtn: "Crop", + customValidationFailed: "Failed to validate file.", + doneBtn: "Done", + fileSizeLimitPrefix: "File size limit:", + finishBtn: "Finished", + finishBtnIcon: true, + imageCropNumberPrefix: "Image", + maxFilesReachedPrefix: "Maximum number of files:", + maxImagesReachedPrefix: "Maximum number of images:", + orDragDropFile: "...or drag and drop a file.", + orDragDropFileMulti: "...or drag and drop files.", + orDragDropImage: "...or drag and drop an image.", + orDragDropImageMulti: "...or drag and drop images.", + processingFile: "Processing file...", + removeBtn: "remove", + removeBtnClicked: "removed", + submitBtnError: "Error!", + submitBtnLoading: "Please wait...", + unsupportedFileType: "File type not supported.", + uploadFileBtn: "Upload a File", + uploadFileMultiBtn: "Upload Files", + uploadImageBtn: "Upload an Image", + uploadImageMultiBtn: "Upload Images", + xOfY: "of" } ``` diff --git a/examples/src/index.ts b/examples/src/index.ts index 5e23166..f9e9bc9 100644 --- a/examples/src/index.ts +++ b/examples/src/index.ts @@ -50,6 +50,7 @@ const dropZoneInitialConfig: UploadWidgetConfig = { allowResizeOnMove: false } }, + locale: {}, styles: { colors: { primary: "#8b63f1" diff --git a/lib/src/components/widgets/uploadWidget/UploadWidget.tsx b/lib/src/components/widgets/uploadWidget/UploadWidget.tsx index a685924..c7f1f2d 100644 --- a/lib/src/components/widgets/uploadWidget/UploadWidget.tsx +++ b/lib/src/components/widgets/uploadWidget/UploadWidget.tsx @@ -208,7 +208,7 @@ export const UploadWidget = ({ resolve, options, upload }: Props): JSX.Element = const { maxFileSizeBytes, mimeTypes, onPreUpload } = options; if (maxFileSizeBytes !== undefined && file.size > maxFileSizeBytes) { - raiseValidationError(`${options.locale.maxSize} ${humanFileSize(maxFileSizeBytes)}`); + raiseValidationError(`${options.locale.fileSizeLimitPrefix} ${humanFileSize(maxFileSizeBytes)}`); } if (!isValidMimeType(mimeTypes, file)) { raiseValidationError(options.locale.unsupportedFileType); diff --git a/lib/src/components/widgets/uploadWidget/components/buttons/SubmitButton.tsx b/lib/src/components/widgets/uploadWidget/components/buttons/SubmitButton.tsx index f25e833..39ebe0d 100644 --- a/lib/src/components/widgets/uploadWidget/components/buttons/SubmitButton.tsx +++ b/lib/src/components/widgets/uploadWidget/components/buttons/SubmitButton.tsx @@ -35,7 +35,7 @@ export const SubmitButton = ({ busyText, idleText, locale, onSubmit, showIcon }: return ( ); diff --git a/lib/src/components/widgets/uploadWidget/components/editors/ImageEditorButtons.tsx b/lib/src/components/widgets/uploadWidget/components/editors/ImageEditorButtons.tsx index 993e0d7..9a71d83 100644 --- a/lib/src/components/widgets/uploadWidget/components/editors/ImageEditorButtons.tsx +++ b/lib/src/components/widgets/uploadWidget/components/editors/ImageEditorButtons.tsx @@ -22,13 +22,13 @@ export const ImageEditorButtons = ({ options, onFinish }: Props): JSX.Element => ); }} className="btn"> - {locale.cancelInPreviewWindow} + {locale.cancelPreviewBtn} await onFinish(true)} locale={locale} - idleText={locale.continue} - busyText={locale.pleaseWait} + idleText={locale.continueBtn} + busyText={locale.submitBtnLoading} showIcon={false} /> diff --git a/lib/src/components/widgets/uploadWidget/components/editors/ImageEditorHeader.tsx b/lib/src/components/widgets/uploadWidget/components/editors/ImageEditorHeader.tsx index 8a191bb..7974ee7 100644 --- a/lib/src/components/widgets/uploadWidget/components/editors/ImageEditorHeader.tsx +++ b/lib/src/components/widgets/uploadWidget/components/editors/ImageEditorHeader.tsx @@ -13,7 +13,7 @@ export const getImageEditorHeader = ({ imageCount, imageIndex, options }: Props) return multi === undefined || multi.imageCount === 1 ? undefined : ( - {locale.image} {multi.imageIndex + 1} {locale.of} {multi.imageCount} + {locale.imageCropNumberPrefix} {multi.imageIndex + 1} {locale.xOfY} {multi.imageCount} ); }; diff --git a/lib/src/components/widgets/uploadWidget/components/files/SubmittedFileComponent.tsx b/lib/src/components/widgets/uploadWidget/components/files/SubmittedFileComponent.tsx index 668fcb4..226a2df 100644 --- a/lib/src/components/widgets/uploadWidget/components/files/SubmittedFileComponent.tsx +++ b/lib/src/components/widgets/uploadWidget/components/files/SubmittedFileComponent.tsx @@ -91,7 +91,7 @@ export const SubmittedFileComponent = ({ file, fileCount, remove, locale, showRe {isDelayedRemove ? ( - {file.type === "uploading" ? locale["cancelled!"] : locale["removed!"]} + {file.type === "uploading" ? locale.cancelBtnClicked : locale.removeBtnClicked} ) : ( <> @@ -103,7 +103,7 @@ export const SubmittedFileComponent = ({ file, fileCount, remove, locale, showRe e.preventDefault(); delayedRemove(); }}> - {file.type === "uploading" ? locale.cancel : locale.remove} + {file.type === "uploading" ? locale.cancelBtn : locale.removeBtn} )} diff --git a/lib/src/components/widgets/uploadWidget/screens/UploaderMainScreen.tsx b/lib/src/components/widgets/uploadWidget/screens/UploaderMainScreen.tsx index 0cb92f1..ca40ec5 100644 --- a/lib/src/components/widgets/uploadWidget/screens/UploaderMainScreen.tsx +++ b/lib/src/components/widgets/uploadWidget/screens/UploaderMainScreen.tsx @@ -57,12 +57,12 @@ export const UploaderMainScreen = ({ (options.maxFileCount === undefined || submittedFiles.length < options.maxFileCount ? ( ) : (
- {isImageUploader ? locale.maxImagesReached : locale.maxFilesReached} {options.maxFileCount} + {isImageUploader ? locale.maxImagesReachedPrefix : locale.maxFilesReachedPrefix} {options.maxFileCount}
))} @@ -78,10 +78,10 @@ export const UploaderMainScreen = ({ }}> {finishedUploading ? ( - {locale.finish} {locale.finishIcon && } + {locale.finishBtn} {locale.finishBtnIcon && } ) : ( - locale.pleaseWait + locale.submitBtnLoading )} )} diff --git a/lib/src/components/widgets/uploadWidget/screens/UploaderWelcomeScreen.tsx b/lib/src/components/widgets/uploadWidget/screens/UploaderWelcomeScreen.tsx index 6bc0d0d..b78ed0e 100644 --- a/lib/src/components/widgets/uploadWidget/screens/UploaderWelcomeScreen.tsx +++ b/lib/src/components/widgets/uploadWidget/screens/UploaderWelcomeScreen.tsx @@ -17,11 +17,11 @@ export const UploaderWelcomeScreen = ({ addFiles, options, isImageUploader }: Pr text={ isImageUploader ? multi - ? locale.uploadImages - : locale.uploadImage + ? locale.uploadImageMultiBtn + : locale.uploadImageBtn : multi - ? locale.uploadFiles - : locale.uploadFile + ? locale.uploadFileMultiBtn + : locale.uploadFileBtn } className="btn--primary btn--upload" onUpload={addFiles} @@ -29,10 +29,10 @@ export const UploaderWelcomeScreen = ({ addFiles, options, isImageUploader }: Pr

{isImageUploader ? multi - ? locale.orDragDropImages + ? locale.orDragDropImageMulti : locale.orDragDropImage : multi - ? locale.orDragDropFiles + ? locale.orDragDropFileMulti : locale.orDragDropFile}

diff --git a/lib/src/config/UploadWidgetConfig.ts b/lib/src/config/UploadWidgetConfig.ts index 2397621..4a8f638 100644 --- a/lib/src/config/UploadWidgetConfig.ts +++ b/lib/src/config/UploadWidgetConfig.ts @@ -1,5 +1,5 @@ import { UploadWidgetLocale } from "@bytescale/upload-widget/modules/locales/UploadWidgetLocale"; -import { UploaderLocaleEnUs } from "@bytescale/upload-widget/modules/locales/EN_US"; +import { UploadWidgetLocaleEnUs } from "@bytescale/upload-widget/modules/locales/EN_US"; import { UploadWidgetLayout } from "@bytescale/upload-widget/config/UploadWidgetLayout"; import { UploadWidgetEditor, UploadWidgetEditorRequired } from "@bytescale/upload-widget/config/UploadWidgetEditor"; import { UploadWidgetStyles, UploadWidgetStylesRequired } from "@bytescale/upload-widget/config/UploadWidgetStyles"; @@ -8,12 +8,14 @@ import { UploadWidgetOnPreUploadResult } from "@bytescale/upload-widget/config/U import { Resolvable } from "@bytescale/upload-widget/modules/common/Resolvable"; import { FilePathDefinition, BytescaleApiClientConfig } from "@bytescale/sdk"; import { UploadWidgetOnUpdateEvent } from "@bytescale/upload-widget/config/UploadWidgetOnUpdateEvent"; +import { UploadWidgetLocaleDeprecatedFields } from "@bytescale/upload-widget/modules/locales/UploadWidgetLocaleDeprecatedFields"; +import { removeUndefinedAndNullFields } from "@bytescale/upload-widget/modules/common/ObjectUtils"; export interface UploadWidgetConfig extends BytescaleApiClientConfig { container?: string | HTMLElement; editor?: UploadWidgetEditor; layout?: UploadWidgetLayout; - locale?: UploadWidgetLocale; + locale?: Partial & Partial; maxFileCount?: number; maxFileSizeBytes?: number; metadata?: object; @@ -65,8 +67,12 @@ export namespace UploadWidgetConfigRequired { editor: UploadWidgetEditorRequired.from(options.editor), layout, locale: { - ...UploaderLocaleEnUs, // This way ensures if the client code excludes certain entries (e.g. we've added new ones) then we default onto those. - ...options.locale + ...UploadWidgetLocaleEnUs, + // Ensure we don't overwrite defaults with undefined fields. + ...removeUndefinedAndNullFields({ + ...UploadWidgetLocaleDeprecatedFields.migrate(options.locale ?? {}), + ...options.locale + }) }, maxFileCount: options.maxFileCount, maxFileSizeBytes: options.maxFileSizeBytes, diff --git a/lib/src/index.ts b/lib/src/index.ts index fc253f7..86d2f01 100644 --- a/lib/src/index.ts +++ b/lib/src/index.ts @@ -16,4 +16,4 @@ export { UploadWidgetStyles } from "@bytescale/upload-widget/config/UploadWidget export { UploadWidgetEditor } from "@bytescale/upload-widget/config/UploadWidgetEditor"; export { UploadWidgetConfig } from "@bytescale/upload-widget/config/UploadWidgetConfig"; export { UploadWidgetMethods } from "@bytescale/upload-widget/config/UploadWidgetMethods"; -export { UploaderLocaleEnUs } from "@bytescale/upload-widget/modules/locales/EN_US"; +export { UploadWidgetLocaleEnUs } from "@bytescale/upload-widget/modules/locales/EN_US"; diff --git a/lib/src/modules/common/ObjectUtils.ts b/lib/src/modules/common/ObjectUtils.ts new file mode 100644 index 0000000..93d8545 --- /dev/null +++ b/lib/src/modules/common/ObjectUtils.ts @@ -0,0 +1,5 @@ +export function removeUndefinedAndNullFields(value: Partial): Partial { + return Object.fromEntries(Object.entries(value).filter(([, value]) => (value ?? undefined) !== undefined)) as Partial< + T + >; +} diff --git a/lib/src/modules/locales/EN_US.ts b/lib/src/modules/locales/EN_US.ts index f8cfc13..26cdbed 100644 --- a/lib/src/modules/locales/EN_US.ts +++ b/lib/src/modules/locales/EN_US.ts @@ -1,36 +1,34 @@ import { UploadWidgetLocale } from "@bytescale/upload-widget/modules/locales/UploadWidgetLocale"; -export const UploaderLocaleEnUs: UploadWidgetLocale = { - "error!": "Error!", - "done": "Done", - "addAnotherFile": "Add another file...", - "addAnotherImage": "Add another image...", - "cancel": "cancel", - "cancelInPreviewWindow": "Cancel", - "cancelled!": "cancelled", - "continue": "Continue", - "customValidationFailed": "Failed to validate file.", - "crop": "Crop", - "finish": "Finished", - "finishIcon": true, - "image": "Image", - "maxFilesReached": "Maximum number of files:", - "maxImagesReached": "Maximum number of images:", - "maxSize": "File size limit:", - "next": "Next", - "of": "of", - "orDragDropFile": "...or drag and drop a file.", - "orDragDropFiles": "...or drag and drop files.", - "orDragDropImage": "...or drag and drop an image.", - "orDragDropImages": "...or drag and drop images.", - "pleaseWait": "Please wait...", - "removed!": "removed", - "remove": "remove", - "skip": "Skip", - "unsupportedFileType": "File type not supported.", - "uploadFile": "Upload a File", - "uploadFiles": "Upload a File", // We've now chosen to use singular tense for the upload button. - "uploadImage": "Upload an Image", - "uploadImages": "Upload an Image", // We've now chosen to use singular tense for the upload button. - "processingFile": "Processing file..." +export const UploadWidgetLocaleEnUs: UploadWidgetLocale = { + addAnotherFileBtn: "Add another file...", + addAnotherImageBtn: "Add another image...", + cancelBtn: "cancel", + cancelBtnClicked: "cancelled", + cancelPreviewBtn: "Cancel", + continueBtn: "Continue", + cropBtn: "Crop", + customValidationFailed: "Failed to validate file.", + doneBtn: "Done", + fileSizeLimitPrefix: "File size limit:", + finishBtn: "Finished", + finishBtnIcon: true, + imageCropNumberPrefix: "Image", + maxFilesReachedPrefix: "Maximum number of files:", + maxImagesReachedPrefix: "Maximum number of images:", + orDragDropFile: "...or drag and drop a file.", + orDragDropFileMulti: "...or drag and drop files.", + orDragDropImage: "...or drag and drop an image.", + orDragDropImageMulti: "...or drag and drop images.", + processingFile: "Processing file...", + removeBtn: "remove", + removeBtnClicked: "removed", + submitBtnError: "Error!", + submitBtnLoading: "Please wait...", + unsupportedFileType: "File type not supported.", + uploadFileBtn: "Upload a File", + uploadFileMultiBtn: "Upload a File", // We support differentiation even though our default locale does not. + uploadImageBtn: "Upload an Image", + uploadImageMultiBtn: "Upload an Image", // We support differentiation even though our default locale does not. + xOfY: "of" }; diff --git a/lib/src/modules/locales/UploadWidgetLocale.ts b/lib/src/modules/locales/UploadWidgetLocale.ts index c4c0a1f..051af6e 100644 --- a/lib/src/modules/locales/UploadWidgetLocale.ts +++ b/lib/src/modules/locales/UploadWidgetLocale.ts @@ -1,34 +1,32 @@ export interface UploadWidgetLocale { - "addAnotherFile": string; - "addAnotherImage": string; - "cancel": string; - "cancelInPreviewWindow": string; - "cancelled!": string; - "continue": string; - "crop": string; - "customValidationFailed": string; - "done": string; - "error!": string; - "finish": string; - "finishIcon": boolean; - "image": string; - "maxFilesReached": string; - "maxImagesReached": string; - "maxSize": string; - "next": string; - "of": string; - "orDragDropFile": string; - "orDragDropFiles": string; - "orDragDropImage": string; - "orDragDropImages": string; - "pleaseWait": string; - "processingFile": string; - "remove": string; - "removed!": string; - "skip": string; - "unsupportedFileType": string; - "uploadFile": string; - "uploadFiles": string; - "uploadImage": string; - "uploadImages": string; + addAnotherFileBtn: string; + addAnotherImageBtn: string; + cancelBtn: string; + cancelBtnClicked: string; + cancelPreviewBtn: string; + continueBtn: string; + cropBtn: string; + customValidationFailed: string; + doneBtn: string; + fileSizeLimitPrefix: string; + finishBtn: string; + finishBtnIcon: boolean; + imageCropNumberPrefix: string; + maxFilesReachedPrefix: string; + maxImagesReachedPrefix: string; + orDragDropFile: string; + orDragDropFileMulti: string; + orDragDropImage: string; + orDragDropImageMulti: string; + processingFile: string; + removeBtn: string; + removeBtnClicked: string; + submitBtnError: string; + submitBtnLoading: string; + unsupportedFileType: string; + uploadFileBtn: string; + uploadFileMultiBtn: string; + uploadImageBtn: string; + uploadImageMultiBtn: string; + xOfY: string; } diff --git a/lib/src/modules/locales/UploadWidgetLocaleDeprecatedFields.ts b/lib/src/modules/locales/UploadWidgetLocaleDeprecatedFields.ts new file mode 100644 index 0000000..859afd0 --- /dev/null +++ b/lib/src/modules/locales/UploadWidgetLocaleDeprecatedFields.ts @@ -0,0 +1,196 @@ +import { UploadWidgetLocale } from "@bytescale/upload-widget"; + +export interface UploadWidgetLocaleDeprecatedFields { + /** + * @deprecated Use 'locale.addAnotherFileBtn' instead. + */ + "addAnotherFile": string; + + /** + * @deprecated Use 'locale.addAnotherImageBtn' instead. + */ + "addAnotherImage": string; + + /** + * @deprecated Use 'locale.cancelBtn' instead. + */ + "cancel": string; + + /** + * @deprecated Use 'locale.cancelPreviewBtn' instead. + */ + "cancelInPreviewWindow": string; + + /** + * @deprecated Use 'locale.cancelBtnClicked' instead. + */ + "cancelled!": string; + + /** + * @deprecated Use 'locale.continueBtn' instead. + */ + "continue": string; + + /** + * @deprecated Use 'locale.cropBtn' instead. + */ + "crop": string; + + /** + * @deprecated Use 'locale.doneBtn' instead. + */ + "done": string; + + /** + * @deprecated Use 'locale.submitBtnError' instead. + */ + "error!": string; + + /** + * @deprecated Use 'locale.finishBtn' instead. + */ + "finish": string; + + /** + * @deprecated Use 'locale.finishBtnIcon' instead. + */ + "finishIcon": boolean; + + /** + * @deprecated Use 'locale.imageCropNumberPrefix' instead. + */ + "image": string; + + /** + * @deprecated Use 'locale.maxFilesReachedPrefix' instead. + */ + "maxFilesReached": string; + + /** + * @deprecated Use 'locale.maxImagesReachedPrefix' instead. + */ + "maxImagesReached": string; + + /** + * @deprecated Use 'locale.fileSizeLimitPrefix' instead. + */ + "maxSize": string; + + /** + * @deprecated This field is redundant (its text is no-longer used). + */ + "next": string; + + /** + * @deprecated Use 'locale.xOfY' instead. + */ + "of": string; + + /** + * @deprecated Use 'locale.orDragDropFileMulti' instead. + */ + "orDragDropFiles": string; + + /** + * @deprecated Use 'locale.orDragDropImageMulti' instead. + */ + "orDragDropImages": string; + + /** + * @deprecated Use 'locale.submitBtnLoading' instead. + */ + "pleaseWait": string; + + /** + * @deprecated Use 'locale.removeBtn' instead. + */ + "remove": string; + + /** + * @deprecated Use 'locale.removeBtnClicked' instead. + */ + "removed!": string; + + /** + * @deprecated This field is redundant (its text is no-longer used). + */ + "skip": string; + + /** + * @deprecated Use 'locale.uploadFileBtn' instead. + */ + "uploadFile": string; + + /** + * @deprecated Use 'locale.uploadFileMultiBtn' instead. + */ + "uploadFiles": string; + + /** + * @deprecated Use 'locale.uploadImageBtn' instead. + */ + "uploadImage": string; + + /** + * @deprecated Use 'locale.uploadImageMultiBtn' instead. + */ + "uploadImages": string; +} + +export namespace UploadWidgetLocaleDeprecatedFields { + export function migrate({ + "addAnotherFile": addAnotherFileBtn, + "addAnotherImage": addAnotherImageBtn, + "cancel": cancelBtn, + "cancelInPreviewWindow": cancelPreviewBtn, + "cancelled!": cancelBtnClicked, + "continue": continueBtn, + "crop": cropBtn, + "done": doneBtn, + "error!": submitBtnError, + "finish": finishBtn, + "finishIcon": finishBtnIcon, + "image": imageCropNumberPrefix, + "maxFilesReached": maxFilesReachedPrefix, + "maxImagesReached": maxImagesReachedPrefix, + "maxSize": fileSizeLimitPrefix, + "of": xOfY, + "orDragDropFiles": orDragDropFileMulti, + "orDragDropImages": orDragDropImageMulti, + "pleaseWait": submitBtnLoading, + "remove": removeBtn, + "removed!": removeBtnClicked, + "uploadFile": uploadFileBtn, + "uploadFiles": uploadFileMultiBtn, + "uploadImage": uploadImageBtn, + "uploadImages": uploadImageMultiBtn + }: Partial): Partial { + return { + addAnotherFileBtn, + addAnotherImageBtn, + cancelBtn, + cancelBtnClicked, + cancelPreviewBtn, + continueBtn, + cropBtn, + doneBtn, + fileSizeLimitPrefix, + finishBtn, + finishBtnIcon, + imageCropNumberPrefix, + maxFilesReachedPrefix, + maxImagesReachedPrefix, + orDragDropFileMulti, + orDragDropImageMulti, + removeBtn, + removeBtnClicked, + submitBtnError, + submitBtnLoading, + uploadFileBtn, + uploadFileMultiBtn, + uploadImageBtn, + uploadImageMultiBtn, + xOfY + }; + } +}