diff --git a/plugins/BcColumn/templates/plugin/BcMail/Mail/default/confirm.php b/plugins/BcColumn/templates/plugin/BcMail/Mail/default/confirm.php index 26d17f025f..c16b75a595 100755 --- a/plugins/BcColumn/templates/plugin/BcMail/Mail/default/confirm.php +++ b/plugins/BcColumn/templates/plugin/BcMail/Mail/default/confirm.php @@ -3,7 +3,11 @@ * メールフォーム確認ページ */ $this->BcBaser->css('admin/jquery-ui/jquery-ui.min', true); -$this->BcBaser->js(array('vendor/jquery-ui-1.11.4.min', 'vendor/i18n/ui.datepicker-ja'), false); +$jsFiles = ['vendor/jquery-ui-1.11.4.min']; +if ($this->BcBaser->isJapaneseLocale()) { + $jsFiles[] = 'vendor/i18n/ui.datepicker-ja'; +} +$this->BcBaser->js($jsFiles, false); if ($freezed) { $this->Mailform->freeze(); } diff --git a/plugins/BcColumn/templates/plugin/BcMail/Mail/default/index.php b/plugins/BcColumn/templates/plugin/BcMail/Mail/default/index.php index 94bd53190a..be69a16101 100755 --- a/plugins/BcColumn/templates/plugin/BcMail/Mail/default/index.php +++ b/plugins/BcColumn/templates/plugin/BcMail/Mail/default/index.php @@ -3,7 +3,11 @@ * メールフォーム */ $this->BcBaser->css('admin/jquery-ui/jquery-ui.min', true); -$this->BcBaser->js(array('vendor/jquery-ui-1.11.4.min', 'vendor/i18n/ui.datepicker-ja'), false); +$jsFiles = ['vendor/jquery-ui-1.11.4.min']; +if ($this->BcBaser->isJapaneseLocale()) { + $jsFiles[] = 'vendor/i18n/ui.datepicker-ja'; +} +$this->BcBaser->js($jsFiles, false); ?> diff --git a/plugins/BcThemeSample/templates/layout/default.php b/plugins/BcThemeSample/templates/layout/default.php index a7b9f2bbf8..8e2383f9ad 100755 --- a/plugins/BcThemeSample/templates/layout/default.php +++ b/plugins/BcThemeSample/templates/layout/default.php @@ -18,9 +18,13 @@ $request = $this->getRequest(); $attributes = $request->getAttributes(); $base = $attributes['base']; +$jsFiles = []; +if ($this->BcBaser->isJapaneseLocale()) { + $jsFiles[] = 'vendor/i18n/ui.datepicker-ja'; +} ?> - +
BcBaser->charset() ?> @@ -35,14 +39,13 @@ 'editor' ]) ?> = $this->BcBaser->declarationI18n() ?> - BcBaser->js([ + BcBaser->js(array_merge([ 'vendor/jquery-1.11.3.min', 'vendor/jquery-ui-1.11.4.min', 'vendor/jquery.bxslider-4.12.min', 'vendor/jquery.colorbox-1.6.1.min', - 'vendor/i18n/ui.datepicker-ja', 'vendor/jquery-accessibleMegaMenu', - ]); ?> + ], $jsFiles)); ?> BcBaser->js('common.bundle', true, [ 'id' => 'AdminScript', 'data-baseUrl' => h($base), diff --git a/plugins/baser-core/resources/locales/en/baser_core.mo b/plugins/baser-core/resources/locales/en/baser_core.mo index bb0f72aac1..95f37425b1 100644 Binary files a/plugins/baser-core/resources/locales/en/baser_core.mo and b/plugins/baser-core/resources/locales/en/baser_core.mo differ diff --git a/plugins/baser-core/resources/locales/en/baser_core.po b/plugins/baser-core/resources/locales/en/baser_core.po index f79065315a..355c0b1948 100755 --- a/plugins/baser-core/resources/locales/en/baser_core.po +++ b/plugins/baser-core/resources/locales/en/baser_core.po @@ -8577,7 +8577,7 @@ msgstr "Table" #: plugins/bc-admin-third/templates/plugin/BcCustomContent/Admin/element/CustomContents/form.php:54 msgid "テーブルを選択してください" -msgstr "SPlease select Table" +msgstr "Please select Table" #: plugins/bc-admin-third/templates/plugin/BcCustomContent/Admin/element/CustomContents/form.php:58 msgid "コンテンツに紐付けるテーブルを選択します。" @@ -9882,7 +9882,7 @@ msgstr "Received Emails" #: plugins/bc-admin-third/templates/plugin/BcMail/Admin/element/Dashboard/mail_messages.php:34 msgid "{0} 件" -msgstr "%s Items" +msgstr "{0} Items" #: plugins/bc-admin-third/templates/plugin/BcMail/Admin/element/MailContents/form.php:27 msgid "メールフォーム説明文" @@ -15099,15 +15099,10 @@ msgstr "Widgets" #~ msgid "更新日に不正な文字列が入っています。" #~ msgstr "There are invalid strings in Update Date." -#, fuzzy -#~| msgid "PHPの構文エラーが発生しました。" -#~ msgid "草稿欄でPHPの構文エラーが発生しました。" -#~ msgstr "PHP syntax error occured." - #~ msgid "PHPの構文エラーが発生しました。" #~ msgstr "PHP syntax error occured." -#, fuzzy +#~#, fuzzy #~| msgid "このURLの登録は許可されていません。" #~ msgid "スクリプトの入力は許可されていません。" #~ msgstr "This URL's registration is not allowed." diff --git a/plugins/baser-core/src/Utility/BcUtil.php b/plugins/baser-core/src/Utility/BcUtil.php index bed3249eb7..71aee884b4 100644 --- a/plugins/baser-core/src/Utility/BcUtil.php +++ b/plugins/baser-core/src/Utility/BcUtil.php @@ -2317,4 +2317,34 @@ public static function isDevelopmentVersion(): bool return is_dir(ROOT . DS . 'plugins' . DS . 'baser-core'); } + /** + * locale から言語コードを取得する + * + * @param string|null $locale + * @param string $default + * @return string + * @checked + * @noTodo + * @unitTest + */ + public static function getLocaleLanguageCode(?string $locale = null, string $default = 'ja'): string + { + $locale = strtolower((string) ($locale ?? \Cake\I18n\I18n::getLocale())); + return preg_replace('/[_-].*$/', '', $locale) ?: $default; + } + + /** + * 現在の locale が日本語かどうか判定する + * + * @param string|null $locale + * @return bool + * @checked + * @noTodo + * @unitTest + */ + public static function isJapaneseLocale(?string $locale = null): bool + { + return self::getLocaleLanguageCode($locale) === 'ja'; + } + } diff --git a/plugins/baser-core/src/View/Helper/BcBaserHelper.php b/plugins/baser-core/src/View/Helper/BcBaserHelper.php index bf019fe469..6af83e05f1 100755 --- a/plugins/baser-core/src/View/Helper/BcBaserHelper.php +++ b/plugins/baser-core/src/View/Helper/BcBaserHelper.php @@ -2885,4 +2885,30 @@ public function getFullUrl(string $url): string return BcUtil::fullUrl($url); } + /** + * html の lang 属性に使う言語コードを取得する + * + * @return string + * @checked + * @noTodo + * @unitTest + */ + public function getHtmlLang(): string + { + return BcUtil::getLocaleLanguageCode(); + } + + /** + * 現在の locale が日本語かどうか判定する + * + * @return bool + * @checked + * @noTodo + * @unitTest + */ + public function isJapaneseLocale(): bool + { + return BcUtil::isJapaneseLocale(); + } + } diff --git a/plugins/baser-core/src/View/Helper/BcCkeditorHelper.php b/plugins/baser-core/src/View/Helper/BcCkeditorHelper.php index dcc8d10422..29e300eea4 100755 --- a/plugins/baser-core/src/View/Helper/BcCkeditorHelper.php +++ b/plugins/baser-core/src/View/Helper/BcCkeditorHelper.php @@ -11,6 +11,7 @@ namespace BaserCore\View\Helper; +use BaserCore\Utility\BcUtil; use Cake\Core\Plugin; use Cake\View\Helper; use Cake\Utility\Inflector; @@ -207,8 +208,21 @@ public function initialize($config): void */ protected function build($fieldName, $options = []) { + static $langExistsCache = []; + + $editorLanguage = BcUtil::getLocaleLanguageCode(); + + if (!isset($langExistsCache[$editorLanguage])) { + // CKEditor の言語JSがない場合、要求すると 404 で初期化が失敗するため ja にフォールバック + $editorLanguagePath = Plugin::path('BcAdminThird') . 'webroot' . DS . 'js' . DS . 'vendor' . DS . 'ckeditor' . DS . 'lang' . DS . $editorLanguage . '.js'; + $langExistsCache[$editorLanguage] = file_exists($editorLanguagePath); + } + if (!$langExistsCache[$editorLanguage]) { + $editorLanguage = 'ja'; + } + $options = array_merge([ - 'editorLanguage' => 'ja', // 言語 + 'editorLanguage' => $editorLanguage, // 言語 'editorSkin' => 'moono', // スキン 'editorToolType' => 'normal', // ツールバータイプ 'editorToolbar' => [], // ツールバータイプ diff --git a/plugins/baser-core/tests/TestCase/Utility/BcUtilTest.php b/plugins/baser-core/tests/TestCase/Utility/BcUtilTest.php index 784653bb5d..8951dae20b 100644 --- a/plugins/baser-core/tests/TestCase/Utility/BcUtilTest.php +++ b/plugins/baser-core/tests/TestCase/Utility/BcUtilTest.php @@ -179,6 +179,27 @@ public static function isInstallModeDataProvider() ]; } + /** + * locale から言語コードを取得する + */ + public function testGetLocaleLanguageCode(): void + { + $this->assertSame('ja', BcUtil::getLocaleLanguageCode('ja_JP')); + $this->assertSame('en', BcUtil::getLocaleLanguageCode('en_US')); + $this->assertSame('fr', BcUtil::getLocaleLanguageCode('fr-FR')); + $this->assertSame('ja', BcUtil::getLocaleLanguageCode('', 'ja')); + } + + /** + * 日本語 locale かどうか判定する + */ + public function testIsJapaneseLocale(): void + { + $this->assertTrue(BcUtil::isJapaneseLocale('ja_JP')); + $this->assertTrue(BcUtil::isJapaneseLocale('ja')); + $this->assertFalse(BcUtil::isJapaneseLocale('en_US')); + } + /** * Test getVersion * @return void @@ -1545,7 +1566,7 @@ public function testIsSameReferrerAsCurrent($referer, $expected) public static function isSameReferrerAsCurrentDataProvider() { return [ - // refererがnullの場合 + // refererがnullの場合 [null, false], // referer!=$siteDomainの場合 ["/baser/admin", false], diff --git a/plugins/baser-core/tests/TestCase/View/Helper/BcBaserHelperTest.php b/plugins/baser-core/tests/TestCase/View/Helper/BcBaserHelperTest.php index cb3b05d805..693cfc008e 100644 --- a/plugins/baser-core/tests/TestCase/View/Helper/BcBaserHelperTest.php +++ b/plugins/baser-core/tests/TestCase/View/Helper/BcBaserHelperTest.php @@ -458,6 +458,34 @@ public function testI18nScript() $this->assertStringContainsString($encoded2, $result); } + /** + * html lang 用の言語コードを取得する + */ + public function testGetHtmlLang(): void + { + $originalLocale = \Cake\I18n\I18n::getLocale(); + try { + \Cake\I18n\I18n::setLocale('ja_JP'); + $this->assertSame('ja', $this->BcBaser->getHtmlLang()); + } finally { + \Cake\I18n\I18n::setLocale($originalLocale); + } + } + + /** + * 現在の locale が日本語かどうか判定する + */ + public function testIsJapaneseLocale(): void + { + $originalLocale = \Cake\I18n\I18n::getLocale(); + try { + \Cake\I18n\I18n::setLocale('ja_JP'); + $this->assertTrue($this->BcBaser->isJapaneseLocale()); + } finally { + \Cake\I18n\I18n::setLocale($originalLocale); + } + } + /** * Test BcBaser->flashが適切なflashメッセージを出力してるかテスト * diff --git a/plugins/baser-core/tests/TestCase/View/Helper/BcCkeditorHelperTest.php b/plugins/baser-core/tests/TestCase/View/Helper/BcCkeditorHelperTest.php index d5b3d1167a..a5a5077e9a 100644 --- a/plugins/baser-core/tests/TestCase/View/Helper/BcCkeditorHelperTest.php +++ b/plugins/baser-core/tests/TestCase/View/Helper/BcCkeditorHelperTest.php @@ -14,6 +14,8 @@ use BaserCore\View\BcAdminAppView; use BaserCore\TestSuite\BcTestCase; use BaserCore\View\Helper\BcCkeditorHelper; +use Cake\Core\Plugin; +use Cake\I18n\I18n; use CakephpFixtureFactories\Scenario\ScenarioAwareTrait; /** @@ -111,6 +113,50 @@ public function testBuild() $this->assertMatchesRegularExpression('/let config = JSON\.parse\(\'\{"ckeditorField/', $jsResult); } + /** + * Test build locale-aware editor language + */ + public function testBuildEditorLanguageByLocale() + { + $this->BcCkeditor->getView()->setTheme('BcAdminThird'); + $request = $this->BcCkeditor->getView()->getRequest()->withAttribute('formTokenData', ['dummy']); + $this->BcCkeditor->getView()->setRequest($request); + $this->BcCkeditor->BcAdminForm->create(); + + $originalLocale = I18n::getLocale(); + try { + I18n::setLocale('en_US'); + $this->execPrivateMethod($this->BcCkeditor, 'build', ['Page.contents', []]); + $jsResult = $this->BcCkeditor->getView()->fetch('script'); + $editorLanguagePath = Plugin::path('BcAdminThird') . 'webroot' . DS . 'js' . DS . 'vendor' . DS . 'ckeditor' . DS . 'lang' . DS . 'en.js'; + $this->assertFileExists($editorLanguagePath); + $this->assertStringContainsString('"language":"en"', $jsResult); + } finally { + I18n::setLocale($originalLocale); + } + } + + /** + * Test build falls back to ja for unsupported locale + */ + public function testBuildEditorLanguageFallbackToJa() + { + $this->BcCkeditor->getView()->setTheme('BcAdminThird'); + $request = $this->BcCkeditor->getView()->getRequest()->withAttribute('formTokenData', ['dummy']); + $this->BcCkeditor->getView()->setRequest($request); + $this->BcCkeditor->BcAdminForm->create(); + + $originalLocale = I18n::getLocale(); + try { + I18n::setLocale('fr_FR'); + $this->execPrivateMethod($this->BcCkeditor, 'build', ['Page.contents', []]); + $jsResult = $this->BcCkeditor->getView()->fetch('script'); + $this->assertStringContainsString('"language":"ja"', $jsResult); + } finally { + I18n::setLocale($originalLocale); + } + } + /** * Test setEditorToolbar */ diff --git a/plugins/bc-admin-third/templates/Admin/layout/default.php b/plugins/bc-admin-third/templates/Admin/layout/default.php index 5882d6f1d4..2539aa6526 100644 --- a/plugins/bc-admin-third/templates/Admin/layout/default.php +++ b/plugins/bc-admin-third/templates/Admin/layout/default.php @@ -24,9 +24,14 @@ $request = $this->getRequest(); $attributes = $request->getAttributes(); $base = $attributes['base']; +$jsFiles = []; +if ($this->BcBaser->isJapaneseLocale()) { + $jsFiles[] = 'vendor/i18n/ui.datepicker-ja'; + $jsFiles[] = 'vendor/jquery.validate_ja'; +} ?> - + @@ -68,18 +73,16 @@ 'bcConfirmAlertMessage1' => __d('baser_core', 'メッセージを指定してください。'), 'bcConfirmAlertMessage2' => __d('baser_core', 'コールバック処理が登録されていません。') ], ['block' => false]) ?> - BcBaser->js([ + BcBaser->js(array_merge([ 'admin/vendor.bundle', 'vendor/jquery-3.5.1.min', 'vendor/jquery.bt.min', 'vendor/jquery-contextMenu-2.2.0/jquery.contextMenu.min', 'vendor/jquery-ui-1.13.0.min', - 'vendor/i18n/ui.datepicker-ja', 'vendor/jquery.validate.1.19.3.min', - 'vendor/jquery.validate_ja', 'vendor/jquery.form-2.94', 'vendor/jquery.timepicker' - ]) ?> + ], $jsFiles)) ?> BcBaser->js('admin/common.bundle', true, [ 'id' => 'AdminScript', 'data-baseUrl' => h($base), diff --git a/plugins/bc-admin-third/templates/Admin/layout/error.php b/plugins/bc-admin-third/templates/Admin/layout/error.php index 4aa17681a2..4debab9e96 100644 --- a/plugins/bc-admin-third/templates/Admin/layout/error.php +++ b/plugins/bc-admin-third/templates/Admin/layout/error.php @@ -1,5 +1,11 @@ +BcBaser->isJapaneseLocale()) { + $jsFiles[] = 'vendor/i18n/ui.datepicker-ja'; +} +?> - + @@ -12,15 +18,14 @@ 'admin/style', ]) ?> fetch('css') ?> - BcBaser->js([ + BcBaser->js(array_merge([ 'admin/vendor.bundle', 'vendor/vue.min', 'vendor/jquery-3.5.1.min', 'vendor/jquery.bt.min', - 'vendor/jquery-ui-1.11.4.min.js', - 'vendor/i18n/ui.datepicker-ja', + 'vendor/jquery-ui-1.13.0.min', 'vendor/jquery.timepicker', - ]) ?> + ], $jsFiles)) ?> fetch('script') ?> diff --git a/plugins/bc-admin-third/webroot/js/vendor/ckeditor/lang/en.js b/plugins/bc-admin-third/webroot/js/vendor/ckeditor/lang/en.js new file mode 100644 index 0000000000..f8d1a004b2 --- /dev/null +++ b/plugins/bc-admin-third/webroot/js/vendor/ckeditor/lang/en.js @@ -0,0 +1,5 @@ +/* +Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.lang['en']={"wsc":{"btnIgnore":"Ignore","btnIgnoreAll":"Ignore All","btnReplace":"Replace","btnReplaceAll":"Replace All","btnUndo":"Undo","changeTo":"Change to","errorLoading":"Error loading application service host: %s.","ieSpellDownload":"Spell checker not installed. Do you want to download it now?","manyChanges":"Spell check complete: %1 words changed","noChanges":"Spell check complete: No words changed","noMispell":"Spell check complete: No misspellings found","noSuggestions":"- No suggestions -","notAvailable":"Sorry, but service is unavailable now.","notInDic":"Not in dictionary","oneChange":"Spell check complete: One word changed","progress":"Spell check in progress...","title":"Spell Checker","toolbar":"Check Spelling"},"undo":{"redo":"Redo","undo":"Undo"},"toolbar":{"toolbarCollapse":"Collapse Toolbar","toolbarExpand":"Expand Toolbar","toolbarGroups":{"document":"Document","clipboard":"Clipboard/Undo","editing":"Editing","forms":"Forms","basicstyles":"Basic Styles","paragraph":"Paragraph","links":"Links","insert":"Insert","styles":"Styles","colors":"Colors","tools":"Tools"},"toolbars":"Editor toolbars"},"templates":{"button":"Templates","emptyListMsg":"(No templates defined)","insertOption":"Replace actual contents","options":"Template Options","selectPromptMsg":"Please select the template to open in the editor","title":"Content Templates"},"table":{"border":"Border size","caption":"Caption","cell":{"menu":"Cell","insertBefore":"Insert Cell Before","insertAfter":"Insert Cell After","deleteCell":"Delete Cells","merge":"Merge Cells","mergeRight":"Merge Right","mergeDown":"Merge Down","splitHorizontal":"Split Cell Horizontally","splitVertical":"Split Cell Vertically","title":"Cell Properties","cellType":"Cell Type","rowSpan":"Rows Span","colSpan":"Columns Span","wordWrap":"Word Wrap","hAlign":"Horizontal Alignment","vAlign":"Vertical Alignment","alignBaseline":"Baseline","bgColor":"Background Color","borderColor":"Border Color","data":"Data","header":"Header","yes":"Yes","no":"No","invalidWidth":"Cell width must be a number.","invalidHeight":"Cell height must be a number.","invalidRowSpan":"Rows span must be a whole number.","invalidColSpan":"Columns span must be a whole number.","chooseColor":"Choose"},"cellPad":"Cell padding","cellSpace":"Cell spacing","column":{"menu":"Column","insertBefore":"Insert Column Before","insertAfter":"Insert Column After","deleteColumn":"Delete Columns"},"columns":"Columns","deleteTable":"Delete Table","headers":"Headers","headersBoth":"Both","headersColumn":"First column","headersNone":"None","headersRow":"First Row","invalidBorder":"Border size must be a number.","invalidCellPadding":"Cell padding must be a positive number.","invalidCellSpacing":"Cell spacing must be a positive number.","invalidCols":"Number of columns must be a number greater than 0.","invalidHeight":"Table height must be a number.","invalidRows":"Number of rows must be a number greater than 0.","invalidWidth":"Table width must be a number.","menu":"Table Properties","row":{"menu":"Row","insertBefore":"Insert Row Before","insertAfter":"Insert Row After","deleteRow":"Delete Rows"},"rows":"Rows","summary":"Summary","title":"Table Properties","toolbar":"Table","widthPc":"percent","widthPx":"pixels","widthUnit":"width unit"},"stylescombo":{"label":"Styles","panelTitle":"Formatting Styles","panelTitle1":"Block Styles","panelTitle2":"Inline Styles","panelTitle3":"Object Styles"},"specialchar":{"options":"Special Character Options","title":"Select Special Character","toolbar":"Insert Special Character"},"sourcearea":{"toolbar":"Source"},"smiley":{"options":"Smiley Options","title":"Insert a Smiley","toolbar":"Smiley"},"showblocks":{"toolbar":"Show Blocks"},"selectall":{"toolbar":"Select All"},"scayt":{"btn_about":"About SCAYT","btn_dictionaries":"Dictionaries","btn_disable":"Disable SCAYT","btn_enable":"Enable SCAYT","btn_langs":"Languages","btn_options":"Options","text_title":"Spell Check As You Type"},"save":{"toolbar":"Save"},"removeformat":{"toolbar":"Remove Format"},"print":{"toolbar":"Print"},"preview":{"preview":"Preview"},"pastetext":{"button":"Paste as plain text","title":"Paste as Plain Text"},"pastefromword":{"confirmCleanup":"The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?","error":"It was not possible to clean up the pasted data due to an internal error","title":"Paste from Word","toolbar":"Paste from Word"},"pagebreak":{"alt":"Page Break","toolbar":"Insert Page Break for Printing"},"newpage":{"toolbar":"New Page"},"maximize":{"maximize":"Maximize","minimize":"Minimize"},"magicline":{"title":"Insert paragraph here"},"liststyle":{"armenian":"Armenian numbering","bulletedTitle":"Bulleted List Properties","circle":"Circle","decimal":"Decimal (1, 2, 3, etc.)","decimalLeadingZero":"Decimal leading zero (01, 02, 03, etc.)","disc":"Disc","georgian":"Georgian numbering (an, ban, gan, etc.)","lowerAlpha":"Lower Alpha (a, b, c, d, e, etc.)","lowerGreek":"Lower Greek (alpha, beta, gamma, etc.)","lowerRoman":"Lower Roman (i, ii, iii, iv, v, etc.)","none":"None","notset":"