From 647b5e0ccf0a57e96b1e06d730539b9b5a7d8e40 Mon Sep 17 00:00:00 2001 From: rhahao <26148770+rhahao@users.noreply.github.com> Date: Thu, 21 Dec 2023 22:37:50 +0300 Subject: [PATCH] feat(module): add support for Japanese language --- README.md | 3 +- src/browser/utils.browser.ts | 3 +- src/common/parsing_rules.ts | 84 ++++++++--- src/locales/languages.ts | 1 + src/node/utils.node.ts | 3 +- test/enhancedParsing/list.json | 1 + test/fixtures/mwb_J_202309.js | 251 +++++++++++++++++++++++++++++++++ test/fixtures/w_J_202309.js | 37 +++++ 8 files changed, 358 insertions(+), 25 deletions(-) create mode 100644 test/fixtures/mwb_J_202309.js create mode 100644 test/fixtures/w_J_202309.js diff --git a/README.md b/README.md index 2a84a5a9..ab41bdbc 100644 --- a/README.md +++ b/README.md @@ -102,8 +102,9 @@ Currently, we only support enhanced parsing for the following languages: ```bash Enlish French -Italian German +Italian +Japanese Madagascar Sign Language, Malagasy Malagasy Portuguese Brazil diff --git a/src/browser/utils.browser.ts b/src/browser/utils.browser.ts index c1c19c74..fe16172d 100644 --- a/src/browser/utils.browser.ts +++ b/src/browser/utils.browser.ts @@ -3,6 +3,7 @@ import * as path from 'path-browserify'; import E from '../locales/en/text.json'; import F from '../locales/fr-FR/text.json'; import I from '../locales/it-IT/text.json'; +import J from '../locales/ja-JP/text.json'; import K from '../locales/uk-UA/text.json'; import MG from '../locales/mg-MG/text.json'; import T from '../locales/pt-BR/text.json'; @@ -19,6 +20,6 @@ declare global { } window.jw_epub_parser = { - languages: { E, F, I, K, MG, T, TND, TNK, TTM, VZ, X }, + languages: { E, F, I, J, K, MG, T, TND, TNK, TTM, VZ, X }, path: path, }; diff --git a/src/common/parsing_rules.ts b/src/common/parsing_rules.ts index 984e8368..25eb572c 100644 --- a/src/common/parsing_rules.ts +++ b/src/common/parsing_rules.ts @@ -6,18 +6,35 @@ export const extractMonthName = (src: string, lang: string) => { let monthIndex; const text = src.toLowerCase(); - const split = text.split(/[–-—]/); + const separators = ['bis', '–', '-', '—']; + const regex = new RegExp(separators.join('|'), 'gi'); + const split = text.split(regex); const monthNames = getMonthNames(lang); outerLoop: for (const splitted of split) { for (const month of monthNames) { const monthLang = month.name.toLowerCase(); - const regex = new RegExp(`(${monthLang})`); + let searchKey = `(${monthLang})`; + if (lang === 'J') { + searchKey = `\\b${searchKey}\\b`; + } + + const regex = new RegExp(searchKey); const array = regex.exec(splitted); if (Array.isArray(array)) { - varDay = +text.match(/(\d+)/)![0]; + const regex = /\d+/g; + const match = text.match(regex); + + if (lang === 'J') { + varDay = +match![1]; + } + + if (lang !== 'J') { + varDay = +match![0]; + } + monthIndex = month.index; break outerLoop; } @@ -53,8 +70,8 @@ export const extractSourceEnhanced = (src: string, lang: string) => { if (match) { const splits = src.split(regex); const duration = +match[0].match(/\d+/)![0]; - const regexStartColumn = /^[:.]/; - const regexEndColumn = /:$/; + const regexStartColumn = /^[:.「]/; + const regexEndColumn = /[:」]$/; const tmpAssignment = splits[0].trim(); const source = splits[1].trim().replace(regexStartColumn, '').replace(regexEndColumn, '').trim(); @@ -87,16 +104,16 @@ export const extractLastSong = (src: string) => { }; export const extractWTStudyDate = (src: string, lang: string) => { + let varDay; + let monthIndex; + let varYear; + const variations = getStudyArticleDateVariations(lang).split('|'); const patternNumber = '{{ number }}'; const patternDate = '{{ date }}'; - let varDay; - let monthIndex; - let varYear; - - for (const variation of variations) { + outerLoop: for (const variation of variations) { let textSearch = variation.replace(patternDate, ''); textSearch = textSearch.replace(patternNumber, '\\d+'); @@ -110,23 +127,46 @@ export const extractWTStudyDate = (src: string, lang: string) => { textSearch = dateValue.trim(); + const text = textSearch.toLowerCase(); + const separators = ['bis', '–', '-', '—']; + const regex = new RegExp(separators.join('|'), 'gi'); + const split = text.split(regex); const monthNames = getMonthNames(lang); - for (const month of monthNames) { - const monthLang = month.name.toLowerCase(); - const regex = new RegExp(`(${monthLang})`); - const array2 = regex.exec(textSearch.toLowerCase()); + for (const splitted of split) { + for (const month of monthNames) { + const monthLang = month.name.toLowerCase(); + let searchKey = `(${monthLang})`; + + if (lang === 'J') { + searchKey = `\\b${searchKey}\\b`; + } + + const regex = new RegExp(searchKey); + const array2 = regex.exec(splitted); + + if (Array.isArray(array2)) { + const regex = /\d+/g; + const match = textSearch.match(regex); + + if (lang === 'J') { + varDay = +match![2]; + } + + if (lang !== 'J') { + varDay = +match![0]; + } + + monthIndex = month.index; - if (Array.isArray(array2)) { - varDay = +textSearch.match(/(\d+)/)![0]; - monthIndex = month.index; + const findYear = /\b\d{4}\b/; + const array3 = findYear.exec(dateValue); + if (array3 !== null) { + varYear = +array3[0]; + } - const findYear = /\b\d{4}\b/; - const array3 = findYear.exec(dateValue); - if (array3 !== null) { - varYear = +array3[0]; + break outerLoop; } - break; } } } diff --git a/src/locales/languages.ts b/src/locales/languages.ts index abfd67e2..4dc4a0b6 100644 --- a/src/locales/languages.ts +++ b/src/locales/languages.ts @@ -2,6 +2,7 @@ export default [ { locale: 'en', code: 'E' }, { locale: 'fr-FR', code: 'F' }, { locale: 'it-IT', code: 'I' }, + { locale: 'ja-JP', code: 'J' }, { locale: 'uk-UA', code: 'K' }, { locale: 'mg-MG', code: 'MG' }, { locale: 'pt-BR', code: 'T' }, diff --git a/src/node/utils.node.ts b/src/node/utils.node.ts index d3fcc17d..e4727845 100644 --- a/src/node/utils.node.ts +++ b/src/node/utils.node.ts @@ -4,6 +4,7 @@ import { readFile } from 'fs/promises'; import E from '../locales/en/text.json' assert { type: 'json' }; import F from '../locales/fr-FR/text.json' assert { type: 'json' }; import I from '../locales/it-IT/text.json' assert { type: 'json' }; +import J from '../locales/ja-JP/text.json' assert { type: 'json' }; import K from '../locales/uk-UA/text.json' assert { type: 'json' }; import MG from '../locales/mg-MG/text.json' assert { type: 'json' }; import T from '../locales/pt-BR/text.json' assert { type: 'json' }; @@ -18,7 +19,7 @@ declare global { } global.jw_epub_parser = { - languages: { E, F, I, K, MG, T, TND, TNK, TTM, VZ, X }, + languages: { E, F, I, J, K, MG, T, TND, TNK, TTM, VZ, X }, path: path, readFile: readFile, }; diff --git a/test/enhancedParsing/list.json b/test/enhancedParsing/list.json index 145c424a..59da49ac 100644 --- a/test/enhancedParsing/list.json +++ b/test/enhancedParsing/list.json @@ -2,6 +2,7 @@ { "language": "E", "issue": "202309" }, { "language": "F", "issue": "202309" }, { "language": "I", "issue": "202309" }, + { "language": "J", "issue": "202309" }, { "language": "K", "issue": "202309" }, { "language": "MG", "issue": "202309" }, { "language": "TND", "issue": "202309" }, diff --git a/test/fixtures/mwb_J_202309.js b/test/fixtures/mwb_J_202309.js new file mode 100644 index 00000000..626fa936 --- /dev/null +++ b/test/fixtures/mwb_J_202309.js @@ -0,0 +1,251 @@ +export default [ + { + mwb_week_date: '2023/09/04', + mwb_week_date_locale: '9月4-10日', + mwb_weekly_bible_reading: 'エステル 1-2章', + mwb_song_first: 137, + mwb_tgw_talk: 'エステルのような慎み深い人を目指す', + mwb_tgw_bread: 'エス 1:13-22(教励 第10課)', + mwb_ayf_count: 3, + mwb_ayf_part1: + '討議。「最初の話し合い: 王国(マタ 6:9,10)」の動画を再生する。映像が止まったところで動画を一時停止し,画面に表示される質問をする。', + mwb_ayf_part1_time: 5, + mwb_ayf_part1_type: '最初の話し合いの動画', + mwb_ayf_part2: + '話し合いのサンプルの話題に沿って話す。「いつまでも幸せに暮らせます」の冊子を提供する。(教励 第1課)', + mwb_ayf_part2_time: 3, + mwb_ayf_part2_type: '最初の話し合い', + mwb_ayf_part3: '塔研20.11 13-14ページ3-7節 主題: イエスや天使たちによる助け(教励 第14課)', + mwb_ayf_part3_time: 5, + mwb_ayf_part3_type: '話', + mwb_song_middle: 106, + mwb_lc_count: 2, + mwb_lc_part1: '若者のコメント 外見', + mwb_lc_part1_time: 5, + mwb_lc_part1_content: + '討議。動画を再生し,次の質問をする。自分の外見についてバランスが取れた見方をするのが難しいのはなぜか。', + mwb_lc_part2: '組織の活動の進展', + mwb_lc_part2_time: 10, + mwb_lc_part2_content: '組織の活動の進展」の9月の動画を再生する。', + mwb_lc_cbs: '暮 レッスン56,補足情報6と7', + mwb_song_conclude: 101, + }, + { + mwb_week_date: '2023/09/11', + mwb_week_date_locale: '9月11-17日', + mwb_weekly_bible_reading: 'エステル 3-5章', + mwb_song_first: 85, + mwb_tgw_talk: 'ベストを尽くせるよう仲間を助ける', + mwb_tgw_bread: 'エス 3:1-12(教励 第2課)', + mwb_ayf_count: 3, + mwb_ayf_part1: + '討議。「再訪問: 王国(詩 37:11)」の動画を再生する。映像が止まったところで動画を一時停止し,画面に表示される質問をする。', + mwb_ayf_part1_time: 5, + mwb_ayf_part1_type: '再訪問の動画', + mwb_ayf_part2: + '話し合いのサンプルの話題に沿って話す。聖書レッスンについて話し,聖書レッスン紹介用コンタクトカードを渡す。(教励 第16課)', + mwb_ayf_part2_time: 3, + mwb_ayf_part2_type: '再訪問', + mwb_ayf_part3: '暮 レッスン12 序文とポイント1-3(教励 第15課)', + mwb_ayf_part3_time: 5, + mwb_ayf_part3_type: '聖書研究', + mwb_song_middle: 65, + mwb_lc_count: 2, + mwb_lc_part1: 'エホバの友になろう エステルみたいになりたいな', + mwb_lc_part1_time: 5, + mwb_lc_part1_content: + '討議。動画を再生する。もしいれば,前もって選んでおいた子供たちに次の質問をする。エステルの勇気にどのように倣えるか。', + mwb_lc_part2: '会衆の必要', + mwb_lc_part2_time: 10, + mwb_lc_cbs: '暮 レッスン57', + mwb_song_conclude: 125, + }, + { + mwb_week_date: '2023/09/18', + mwb_week_date_locale: '9月18-24日', + mwb_weekly_bible_reading: 'エステル 6-8章', + mwb_song_first: 115, + mwb_tgw_talk: '良いコミュニケーションの手本', + mwb_tgw_bread: 'エス 8:9-17(教励 第5課)', + mwb_ayf_count: 3, + mwb_ayf_part1: '話し合いのサンプルの話題に沿って話す。よくある反対意見に対応する。(教励 第3課)', + mwb_ayf_part1_time: 3, + mwb_ayf_part1_type: '最初の話し合い', + mwb_ayf_part2: + '話し合いのサンプルの話題に沿って話す。集会に招待する。「王国会館においでください」の動画を紹介し,話し合う。(再生はしない)(教励 第12課)', + mwb_ayf_part2_time: 4, + mwb_ayf_part2_type: '再訪問', + mwb_ayf_part3: '塔研22.01 10-11ページ8-10節 主題: ヤコブのように上手に教える シンプルに説明する。(教励 第17課)', + mwb_ayf_part3_time: 5, + mwb_ayf_part3_type: '話', + mwb_song_middle: 148, + mwb_lc_count: 1, + mwb_lc_part1: 'エホバに頼って,いじめに対処する', + mwb_lc_part1_time: 15, + mwb_lc_part1_content: '討議。動画を視聴する。', + mwb_lc_cbs: '暮 レッスン58', + mwb_song_conclude: 124, + }, + { + mwb_week_date: '2023/09/25', + mwb_week_date_locale: '9月25日–10月1日', + mwb_weekly_bible_reading: 'エステル 9-10章', + mwb_song_first: 102, + mwb_tgw_talk: 'モルデカイは他の人のために自分の権限を行使した', + mwb_tgw_bread: 'エス 9:1-14(教励 第11課)', + mwb_ayf_count: 3, + mwb_ayf_part1: '話し合いのサンプルの話題に沿って話す。(教励 第6課)', + mwb_ayf_part1_time: 2, + mwb_ayf_part1_type: '最初の話し合い', + mwb_ayf_part2: + '話し合いのサンプルの話題に沿って話す。「いつまでも幸せに暮らせます」の冊子を提供し,聖書レッスンを実際に行ってみる。(教励 第13課)', + mwb_ayf_part2_time: 5, + mwb_ayf_part2_type: '再訪問', + mwb_ayf_part3: '暮 レッスン12「もっと調べよう」,ポイント4(教励 第19課)', + mwb_ayf_part3_time: 5, + mwb_ayf_part3_type: '聖書研究', + mwb_song_middle: 117, + mwb_lc_count: 1, + mwb_lc_part1: '牧者たちはエホバの民のために働く', + mwb_lc_part1_time: 15, + mwb_lc_part1_content: '討議。動画を視聴する。', + mwb_lc_cbs: '暮 レッスン59 ポイント1-5', + mwb_song_conclude: 55, + }, + { + mwb_week_date: '2023/10/02', + mwb_week_date_locale: '10月2-8日', + mwb_weekly_bible_reading: 'ヨブ 1-3章', + mwb_song_first: 141, + mwb_tgw_talk: 'いつでもエホバへの深い愛を示す', + mwb_tgw_bread: 'ヨブ 3:1-26(教励 第12課)', + mwb_ayf_count: 3, + mwb_ayf_part1: + '話し合いのサンプルの話題に沿って話す。公式ウェブサイトを紹介し,jw.orgコンタクトカードを渡す。(教励 第9課)', + mwb_ayf_part1_time: 3, + mwb_ayf_part1_type: '最初の話し合い', + mwb_ayf_part2: + '話し合いのサンプルの話題に沿って話す。「聖書を学ぶべきなのはなぜですか」の動画を紹介し,話し合う。(再生はしない)(教励 第20課)', + mwb_ayf_part2_time: 4, + mwb_ayf_part2_type: '再訪問', + mwb_ayf_part3: + '塔研22.01 11-12ページ11-14節 主題: ヤコブのように上手に教える 現実的な見方をし,謙遜である。(教励 第18課)', + mwb_ayf_part3_time: 5, + mwb_ayf_part3_type: '話', + mwb_song_middle: 21, + mwb_lc_count: 2, + mwb_lc_part1: '自分はよくやっていると思っていました', + mwb_lc_part1_time: 10, + mwb_lc_part1_content: + '討議。動画を再生し,次の質問をする。バードウェル兄弟が「自分はよくやっている」と思っていたのはなぜか。', + mwb_lc_part2: 'JW.ORGのトップページを宣教で使う', + mwb_lc_part2_time: 5, + mwb_lc_part2_content: '討議。', + mwb_lc_cbs: '暮 レッスン59 ポイント6,まとめ,復習,次のステップ', + mwb_song_conclude: 129, + }, + { + mwb_week_date: '2023/10/09', + mwb_week_date_locale: '10月9-15日', + mwb_weekly_bible_reading: 'ヨブ 4-5章', + mwb_song_first: 121, + mwb_tgw_talk: '間違った情報に気を付ける', + mwb_tgw_bread: 'ヨブ 5:1-27(教励 第10課)', + mwb_ayf_count: 3, + mwb_ayf_part1: '話し合いのサンプルの話題に沿って話す。(教励 第4課)', + mwb_ayf_part1_time: 2, + mwb_ayf_part1_type: '最初の話し合い', + mwb_ayf_part2: '話し合いのサンプルの話題に沿って話す。知りたいことをjw.orgで調べる方法を見せる。(教励 第15課)', + mwb_ayf_part2_time: 5, + mwb_ayf_part2_type: '再訪問', + mwb_ayf_part3: '暮 レッスン16 ポイント5(教励 第16課)', + mwb_ayf_part3_time: 5, + mwb_ayf_part3_type: '聖書研究', + mwb_song_middle: 78, + mwb_lc_count: 1, + mwb_lc_part1: '会衆の必要', + mwb_lc_part1_time: 15, + mwb_lc_cbs: '暮 レッスン60', + mwb_song_conclude: 38, + }, + { + mwb_week_date: '2023/10/16', + mwb_week_date_locale: '10月16-22日', + mwb_weekly_bible_reading: 'ヨブ 6-7章', + mwb_song_first: 33, + mwb_tgw_talk: '生きていくのがつらいとき', + mwb_tgw_bread: 'ヨブ 6:1-21(教励 第2課)', + mwb_ayf_count: 3, + mwb_ayf_part1: '話し合いのサンプルの話題に沿って話す。よくある反対意見に対応する。(教励 第7課)', + mwb_ayf_part1_time: 3, + mwb_ayf_part1_type: '最初の話し合い', + mwb_ayf_part2: '話し合いのサンプルの話題に沿って話す。宣教ツールボックスの出版物を提供する。(教励 第11課)', + mwb_ayf_part2_time: 4, + mwb_ayf_part2_type: '再訪問', + mwb_ayf_part3: '塔研22.01 12-13ページ15-18節 主題: ヤコブのように上手に教える 上手に例えを使う。(教励 第8課)', + mwb_ayf_part3_time: 5, + mwb_ayf_part3_type: '話', + mwb_song_middle: 144, + mwb_lc_count: 1, + mwb_lc_part1: 'エホバは気落ちしている人を支えてくださる', + mwb_lc_part1_time: 15, + mwb_lc_part1_content: '討議。動画を視聴する。', + mwb_lc_cbs: '暮 セクション4の復習', + mwb_song_conclude: 143, + }, + { + mwb_week_date: '2023/10/23', + mwb_week_date_locale: '10月23-29日', + mwb_weekly_bible_reading: 'ヨブ 8-10章', + mwb_song_first: 107, + mwb_tgw_talk: '神の揺るぎない愛によってサタンのうそから守られる', + mwb_tgw_bread: 'ヨブ 9:20-35(教励 第11課)', + mwb_ayf_count: 3, + mwb_ayf_part1: '話し合いのサンプルの話題に沿って話す。宣教ツールボックスの出版物を提供する。(教励 第17課)', + mwb_ayf_part1_time: 3, + mwb_ayf_part1_type: '最初の話し合い', + mwb_ayf_part2: + '話し合いのサンプルの話題に沿って話す。「いつまでも幸せに暮らせます」の冊子を提供し,「この冊子の特徴」の部分を簡単に説明する。(教励 第3課)', + mwb_ayf_part2_time: 4, + mwb_ayf_part2_type: '再訪問', + mwb_ayf_part3: '暮 レッスン16 ポイント6と「こう言う人もいる」(教励 第14課)', + mwb_ayf_part3_time: 5, + mwb_ayf_part3_type: '聖書研究', + mwb_song_middle: 109, + mwb_lc_count: 2, + mwb_lc_part1: '宗教心のない人が神を知るよう助ける', + mwb_lc_part1_time: 10, + mwb_lc_part1_content: '討議。動画を視聴する。', + mwb_lc_part2: '会衆の必要', + mwb_lc_part2_time: 5, + mwb_lc_cbs: '徹「統治体からの手紙」と1章1-7節', + mwb_song_conclude: 64, + }, + { + mwb_week_date: '2023/10/30', + mwb_week_date_locale: '10月30日–11月5日', + mwb_weekly_bible_reading: 'ヨブ 11-12章', + mwb_song_first: 87, + mwb_tgw_talk: '知恵を取り入れて役立てる3つの方法', + mwb_tgw_bread: 'ヨブ 12:1-25(教励 第5課)', + mwb_ayf_count: 3, + mwb_ayf_part1: + '話し合いのサンプルの話題に沿って話す。聖書レッスンについて話し,聖書レッスン紹介用コンタクトカードを渡す。(教励 第1課)', + mwb_ayf_part1_time: 4, + mwb_ayf_part1_type: '最初の話し合い', + mwb_ayf_part2: + '話し合いのサンプルの話題に沿って話す。集会に招待する。「王国会館においでください」の動画を紹介し,話し合う。(再生はしない)(教励 第13課)', + mwb_ayf_part2_time: 3, + mwb_ayf_part2_type: '再訪問', + mwb_ayf_part3: '暮 レッスン12 まとめ,復習,次のステップ(教励 第19課)', + mwb_ayf_part3_time: 5, + mwb_ayf_part3_type: '聖書研究', + mwb_song_middle: 135, + mwb_lc_count: 1, + mwb_lc_part1: '親の皆さん,神からの知恵を学ぶよう子供を助けてください', + mwb_lc_part1_time: 15, + mwb_lc_part1_content: '討議。動画を視聴する。', + mwb_lc_cbs: '徹 1章8-15節,12ページの囲み', + mwb_song_conclude: 3, + }, +]; diff --git a/test/fixtures/w_J_202309.js b/test/fixtures/w_J_202309.js new file mode 100644 index 00000000..43690f56 --- /dev/null +++ b/test/fixtures/w_J_202309.js @@ -0,0 +1,37 @@ +export default [ + { + w_study_date: '2023/11/06', + w_study_date_locale: '研究記事37: 2023年11月6-12日', + w_study_title: 'サムソンのようにエホバに頼る', + w_study_opening_song: 30, + w_study_concluding_song: 3, + }, + { + w_study_date: '2023/11/13', + w_study_date_locale: '研究記事38: 2023年11月13-19日', + w_study_title: '若い皆さん,どんな人生を送りたいですか', + w_study_opening_song: 135, + w_study_concluding_song: 144, + }, + { + w_study_date: '2023/11/20', + w_study_date_locale: '研究記事39: 2023年11月20-26日', + w_study_title: '温和な人は強い人', + w_study_opening_song: 120, + w_study_concluding_song: 88, + }, + { + w_study_date: '2023/11/27', + w_study_date_locale: '研究記事40: 2023年11月27日–12月3日', + w_study_title: '決して諦めなかったペテロに倣う', + w_study_opening_song: 38, + w_study_concluding_song: 126, + }, + { + w_study_date: '2023/12/04', + w_study_date_locale: '研究記事41: 2023年12月4-10日', + w_study_title: 'ペテロの2通の手紙から学べること', + w_study_opening_song: 127, + w_study_concluding_song: 109, + }, +];