diff --git a/packages/docs/fluent-editor/demos/i18n-custom.vue b/packages/docs/fluent-editor/demos/i18n-custom.vue index 658d957..74ef4e2 100644 --- a/packages/docs/fluent-editor/demos/i18n-custom.vue +++ b/packages/docs/fluent-editor/demos/i18n-custom.vue @@ -20,14 +20,17 @@ onMounted(() => { ], 'counter': true, 'better-table': true, + 'i18n': { + lang: 'zh-CN', + langText: { + 'copy-cells': '复制单元格', + 'copy-table': '复制表格', + 'cut-cells': '剪切单元格', + 'empty-cells': '清空单元格', + }, + }, }, - lang: 'zh-CN', - langText: { - 'copy-cells': '复制单元格', - 'copy-table': '复制表格', - 'cut-cells': '剪切单元格', - 'empty-cells': '清空单元格', - }, + }) }) }) diff --git a/packages/docs/fluent-editor/demos/i18n.vue b/packages/docs/fluent-editor/demos/i18n.vue index 397b81a..272aa48 100644 --- a/packages/docs/fluent-editor/demos/i18n.vue +++ b/packages/docs/fluent-editor/demos/i18n.vue @@ -21,14 +21,16 @@ onMounted(() => { ], 'counter': true, 'better-table': true, + 'i18n': { + lang: lang.value, + }, }, - lang: lang.value, }) }) }) function switchLanguage() { lang.value = lang.value === 'zh-CN' ? 'en-US' : 'zh-CN' - editor.changeLanguage({ lang: lang.value }) + editor.getModule('i18n').changeLanguage({ lang: lang.value }) } diff --git a/packages/fluent-editor/src/config/types/editor-config.interface.ts b/packages/fluent-editor/src/config/types/editor-config.interface.ts index d716174..0f4df90 100644 --- a/packages/fluent-editor/src/config/types/editor-config.interface.ts +++ b/packages/fluent-editor/src/config/types/editor-config.interface.ts @@ -14,10 +14,10 @@ export interface IEditorConfig extends QuillOptions { autoProtocol?: boolean | string editorPaste?: any uploadOption?: { - imageUpload?: ({ file: File, callback, editor }) => void + imageUpload?: ({ file, callback, editor }) => void imageAccept?: Array[] | string fileAccept?: Array[] | string - fileUpload: ({ file: File, callback, editor }) => void + fileUpload: ({ file, callback, editor }) => void isVideoPlay?: boolean maxSize?: number success?: (file: File) => void @@ -25,6 +25,8 @@ export interface IEditorConfig extends QuillOptions { multiple?: boolean } screenshot?: Partial - lang?: string - langText?: Record + i18n?: { + lang?: string + langText?: Record + } } diff --git a/packages/fluent-editor/src/counter/index.ts b/packages/fluent-editor/src/counter/index.ts index 817055c..d37a27f 100644 --- a/packages/fluent-editor/src/counter/index.ts +++ b/packages/fluent-editor/src/counter/index.ts @@ -11,7 +11,7 @@ export default class Counter { this.options = this.resolveOptions(options) this.container = quill.addContainer('ql-counter') quill.on(Quill.events.TEXT_CHANGE, this.renderCount) - this.quill.on(CHANGE_LANGUAGE_EVENT, () => { + this.quill.emitter.on(CHANGE_LANGUAGE_EVENT, () => { this.options = this.resolveOptions(options) this.renderCount() }) @@ -22,7 +22,7 @@ export default class Counter { return Object.assign({ format: 'text', unit: 'char', - template: this.quill.options.langText['counter-template'], + template: this.quill.langText['counter-template'], count: 500, }, options) } @@ -33,7 +33,7 @@ export default class Counter { const { format, count: totalCount, unit, template: counterTemplate, errorTemplate } = this.options const count = this.getContentLength(format) const restCount = totalCount - count - const countUnit = unit === 'char' ? this.quill.options.langText.char : this.quill.options.langText.word + const countUnit = unit === 'char' ? this.quill.langText.char : this.quill.langText.word let template: any = counterTemplate if (typeof template === 'function') { template = template(count, restCount) @@ -43,7 +43,7 @@ export default class Counter { .replace('{{restCount}}', String(restCount)) .replace(/{{countUnit}}/g, countUnit) - let limitTemplate: any = errorTemplate || this.quill.options.langText['counter-limit-tips'] + let limitTemplate: any = errorTemplate || this.quill.langText['counter-limit-tips'] if (typeof limitTemplate === 'function') { limitTemplate = limitTemplate(count, restCount) } diff --git a/packages/fluent-editor/src/custom-clipboard.ts b/packages/fluent-editor/src/custom-clipboard.ts index e1724ac..7d24694 100644 --- a/packages/fluent-editor/src/custom-clipboard.ts +++ b/packages/fluent-editor/src/custom-clipboard.ts @@ -154,7 +154,7 @@ class CustomClipboard extends Clipboard { let loadingTipsContainer if (deltaLength > BIG_DELTA_LIMIT) { loadingTipsContainer = this.quill.addContainer('ql-loading-tips') - loadingTipsContainer.innerHTML = this.quill.options.langText.pasting + loadingTipsContainer.innerHTML = this.quill.langText.pasting } const linePos = { index: range.index, length: range.length, fix: 0 } @@ -471,7 +471,7 @@ class CustomClipboard extends Clipboard { else { // 剪切板中无图片,用失败占位图替换 const errorImagePlaceholderJpg - = this.quill.options.langText['img-error'] === 'Image Copy Error' + = this.quill.langText['img-error'] === 'Image Copy Error' ? ERROR_IMAGE_PLACEHOLDER_EN : ERROR_IMAGE_PLACEHOLDER_CN file = await imageUrlToFile(errorImagePlaceholderJpg, true) diff --git a/packages/fluent-editor/src/fluent-editor.ts b/packages/fluent-editor/src/fluent-editor.ts index 896b56e..7d2faa2 100644 --- a/packages/fluent-editor/src/fluent-editor.ts +++ b/packages/fluent-editor/src/fluent-editor.ts @@ -3,7 +3,7 @@ import type { IEditorConfig } from './config/types' import Quill from 'quill' import HeaderList from 'quill-header-list' import { FontStyle, LineHeightStyle, SizeStyle, TextIndentStyle } from './attributors' -import { CHANGE_LANGUAGE_EVENT, defaultLanguage, getListValue, ICONS_CONFIG, inputFile, LANG_CONF } from './config' +import { getListValue, ICONS_CONFIG, inputFile } from './config' import Counter from './counter' // 字符统计 import CustomClipboard from './custom-clipboard' // 粘贴板 import CustomImage from './custom-image/BlotFormatter' // 图片 @@ -14,6 +14,7 @@ import Emoji from './emoji' // 表情 import FileModule from './file' // 文件 import { FormatPainter } from './format-painter' import { fullscreenHandler } from './fullscreen/handler' +import { I18N } from './i18n' import Link from './link' // 超链接 import MathliveModule from './mathlive' // latex公式 import MathliveBlot from './mathlive/formats' @@ -24,42 +25,18 @@ import Strike from './strike' // 删除线 import CustomSyntax from './syntax' // 代码块高亮 import BetterTable from './table/better-table' // 表格 import Toolbar, { ToolbarTip } from './toolbar' // 工具栏 -import { isUndefined } from './utils/is' import Video from './video' // 视频 // import GlobalLink from './global-link' // 全局链接 // import QuickMenu from './quick-menu' // 快捷菜单 -export interface I18NOptions { - lang: string - langText: Record -} -function resolveLanguageOption(options: Partial): I18NOptions { - if (isUndefined(options.lang)) { - options.lang = defaultLanguage - } - if (!(options.lang in LANG_CONF)) { - console.warn(`The language ${options.lang} is not supported. Use the default language: ${defaultLanguage}`) - options.lang = defaultLanguage - } - return { - lang: options.lang, - langText: Object.assign({}, LANG_CONF[options.lang], options.langText || {}), - } -} + export class FluentEditor extends Quill { isFullscreen: boolean = false options: IEditorConfig & ExpandedQuillOptions + lang: string + langText: Record constructor(container: HTMLElement | string, options: IEditorConfig = {}) { - options = Object.assign(options, resolveLanguageOption(options || {})) super(container, options) } - - changeLanguage(options: Partial) { - const langOps = resolveLanguageOption(options) - if (langOps.lang === this.options.lang) return - this.options.lang = langOps.lang - this.options.langText = langOps.langText - this.emitter.emit(CHANGE_LANGUAGE_EVENT, this.options.lang, this.options.langText) - } } const registerModules = function () { @@ -71,6 +48,7 @@ const registerModules = function () { const SnowTheme = Quill.imports['themes/snow'] as typeof Module SnowTheme.DEFAULTS = { modules: { + 'i18n': true, 'keyboard': { bindings: { ...BetterTable.keyboardBindings, @@ -183,6 +161,7 @@ const registerModules = function () { FluentEditor.register( { + 'modules/i18n': I18N, 'modules/toolbar': Toolbar, 'modules/mention': Mention, 'modules/clipboard': CustomClipboard, diff --git a/packages/fluent-editor/src/i18n/index.ts b/packages/fluent-editor/src/i18n/index.ts new file mode 100644 index 0000000..51a3b21 --- /dev/null +++ b/packages/fluent-editor/src/i18n/index.ts @@ -0,0 +1,49 @@ +import type { FluentEditor } from '../fluent-editor' +import { CHANGE_LANGUAGE_EVENT, defaultLanguage, LANG_CONF } from '../config' +import { isUndefined } from '../utils/is' + +export interface I18NOptions { + lang: string + langText: Record +} + +export class I18N { + isFullscreen: boolean = false + options: I18NOptions = { + lang: 'en-US', + langText: LANG_CONF['en-US'], + } + + constructor(public quill: FluentEditor, options: Partial) { + this.options = Object.assign({}, options, this.resolveLanguageOption(options || {})) + this.changeLanguage(this.options) + } + + resolveLanguageOption(options: Partial): I18NOptions { + if (isUndefined(options.lang)) { + options.lang = defaultLanguage + } + if (!(options.lang in LANG_CONF)) { + console.warn(`The language ${options.lang} is not supported. Use the default language: ${defaultLanguage}`) + options.lang = defaultLanguage + } + return { + lang: options.lang, + langText: Object.assign({}, LANG_CONF[options.lang], options.langText || {}), + } + } + + setLangTextToInstance() { + this.quill.langText = this.options.langText + this.quill.lang = this.options.lang + } + + changeLanguage(options: Partial) { + const langOps = this.resolveLanguageOption(options) + if (langOps.lang === this.quill.lang) return + this.options.lang = langOps.lang + this.options.langText = langOps.langText + this.setLangTextToInstance() + this.quill.emitter.emit(CHANGE_LANGUAGE_EVENT, this.options.lang, this.options.langText) + } +} diff --git a/packages/fluent-editor/src/link/modules/tooltip.ts b/packages/fluent-editor/src/link/modules/tooltip.ts index 9202394..fc37365 100644 --- a/packages/fluent-editor/src/link/modules/tooltip.ts +++ b/packages/fluent-editor/src/link/modules/tooltip.ts @@ -40,14 +40,14 @@ export default class Tooltip extends BaseTooltip { LinkBlot.autoProtocol = this.options.autoProtocol this.debouncedHideToolTip = debounce(this.hideToolTip, 300) this.debouncedShowToolTip = debounce(this.showToolTip, 300) - this.quill.on(CHANGE_LANGUAGE_EVENT, () => { + this.quill.emitter.on(CHANGE_LANGUAGE_EVENT, () => { this.setTemplate() }) } setTemplate() { this.root.innerHTML = [ - ``, + ``, '', '', '', diff --git a/packages/fluent-editor/src/table/modules/table-operation-menu.ts b/packages/fluent-editor/src/table/modules/table-operation-menu.ts index 5d37a31..2910a42 100644 --- a/packages/fluent-editor/src/table/modules/table-operation-menu.ts +++ b/packages/fluent-editor/src/table/modules/table-operation-menu.ts @@ -51,7 +51,7 @@ export default class TableOperationMenu { this.selectedTds = this.tableSelection.selectedTds this.destroyHandler = this.destroy.bind(this) this.columnToolCells = this.tableColumnTool.colToolCells() - this.DEFAULT_COLOR_SUBTITLE = this.quill.options.langText['sub-title-bg-color'] + this.DEFAULT_COLOR_SUBTITLE = this.quill.langText['sub-title-bg-color'] this.colorSubTitle = options.color && options.color.text ? options.color.text @@ -66,13 +66,13 @@ export default class TableOperationMenu { document.addEventListener('click', this.destroyHandler, false) this.quill.on(CHANGE_LANGUAGE_EVENT, () => { this.destroy() - this.DEFAULT_COLOR_SUBTITLE = this.quill.options.langText['sub-title-bg-color'] + this.DEFAULT_COLOR_SUBTITLE = this.quill.langText['sub-title-bg-color'] this.setDefaultMenu() }) } setDefaultMenu() { - const langText = this.quill.options.langText + const langText = this.quill.langText this.DEFAULT_MENU = { copyCells: { text: langText['copy-cells'], diff --git a/packages/fluent-editor/src/toolbar/toolbar-tip.ts b/packages/fluent-editor/src/toolbar/toolbar-tip.ts index b4d85cf..7ca53f6 100644 --- a/packages/fluent-editor/src/toolbar/toolbar-tip.ts +++ b/packages/fluent-editor/src/toolbar/toolbar-tip.ts @@ -11,7 +11,7 @@ export class ToolbarTip extends QuillToolbarTip { } super(quill, options) - this.quill.on(CHANGE_LANGUAGE_EVENT, () => { + this.quill.emitter.on(CHANGE_LANGUAGE_EVENT, () => { this.destroyAllTips() this.options = this.resolveOptions(options) this.createToolbarTip() @@ -20,7 +20,8 @@ export class ToolbarTip extends QuillToolbarTip { resolveOptions(options: Partial): QuillToolbarTipOptions { const result = super.resolveOptions(options) - const langText = this.quill.options.langText + if (!this.quill.lang) return result + const langText = this.quill.langText const btnTips = [ 'bold', 'italic',