@@ -12,11 +12,12 @@ const GlossaryInjector: React.FC<GlossaryInjectorProps> = ({ children }) => {
1212 useEffect ( ( ) => {
1313 const url = window . location . pathname ;
1414 let glossaryPath = '/docs/glossary.json' ; // Use the English version as the default glossary.
15+ const isJapaneseSite = url . startsWith ( '/ja-jp/docs' ) ;
1516
1617 if ( process . env . NODE_ENV === 'production' ) { // The glossary tooltip works only in production environments.
17- glossaryPath = url . startsWith ( '/ja-jp/docs' ) ? '/ja-jp/glossary.json' : '/docs/glossary.json' ;
18+ glossaryPath = isJapaneseSite ? '/ja-jp/glossary.json' : '/docs/glossary.json' ;
1819 } else {
19- glossaryPath = url . startsWith ( '/ja-jp/docs' ) ? '/ja-jp/glossary.json' : '/docs/glossary.json' ;
20+ glossaryPath = isJapaneseSite ? '/ja-jp/glossary.json' : '/docs/glossary.json' ;
2021 }
2122
2223 fetch ( glossaryPath )
@@ -50,7 +51,7 @@ const GlossaryInjector: React.FC<GlossaryInjectorProps> = ({ children }) => {
5051 useEffect ( ( ) => {
5152 if ( Object . keys ( glossary ) . length === 0 || isVersionIndexPage ( ) ) return ;
5253
53- // Sort terms in descending order by length to prioritize multi-word terms.
54+ // Sort terms in descending order to prioritize multi-word terms.
5455 const terms = Object . keys ( glossary ) . sort ( ( a , b ) => b . length - a . length ) ;
5556 const processedTerms = new Set < string > ( ) ; // Set to track processed terms.
5657
@@ -93,26 +94,52 @@ const GlossaryInjector: React.FC<GlossaryInjectorProps> = ({ children }) => {
9394 const newNodes : Node [ ] = [ ] ;
9495 let hasReplacements = false ;
9596
96- // Create a regex pattern to match both exact terms and their plural forms.
97+ // Check if the visitor is on the Japanese version of the site.
98+ const isJapaneseSite = window . location . pathname . startsWith ( '/ja-jp/' ) ;
99+
100+ // Create a regex pattern based on the language.
97101 const regexPattern = terms . map ( term => {
98102 const escapedTerm = term . replace ( / [ - \/ \\ ^ $ * + ? . ( ) | [ \] { } ] / g, '\\$&' ) ;
99- // Match exact term or term followed by 's' or 'es' at word boundary.
100- return `(\\b${ escapedTerm } (s|es)?\\b)` ;
103+
104+ // For the Japanese version of the site, don't use word boundaries that don't work well with Japanese characters.
105+ if ( isJapaneseSite ) {
106+ // For Japanese text, we can't use word boundaries, so just match the exact term.
107+ return `(${ escapedTerm } )` ;
108+ }
109+
110+ // For English site, match exact term or term followed by 's' or 'es' at word boundary.
111+ return `(\\b${ escapedTerm } \\b|\\b${ escapedTerm } s\\b|\\b${ escapedTerm } es\\b)` ;
101112 } ) . join ( '|' ) ;
102- const regex = new RegExp ( regexPattern , 'gi' ) ; // The 'i' flag is for case-insensitive matching.
113+
114+ const regex = new RegExp ( regexPattern , 'gi' ) ; // Use case-insensitive matching.
103115
104116 let lastIndex = 0 ;
105117 let match : RegExpExecArray | null ;
106118
107119 while ( ( match = regex . exec ( currentText ) ) ) {
108120 const matchedText = match [ 0 ] ; // The full matched text (may include plural suffix).
109121
110- // Find the base term from the glossary that matches (without plural).
111- const baseTerm = terms . find ( term =>
112- matchedText . toLowerCase ( ) === term . toLowerCase ( ) ||
113- matchedText . toLowerCase ( ) === `${ term . toLowerCase ( ) } s` ||
114- matchedText . toLowerCase ( ) === `${ term . toLowerCase ( ) } es`
115- ) ;
122+ // For Japanese, remove any non-word characters that were captured by the regex.
123+ const actualMatch = isJapaneseSite
124+ ? matchedText . replace ( / ^ [ ^ \p{ L} \p{ N} _ ] + | [ ^ \p{ L} \p{ N} _ ] + $ / gu, '' )
125+ : matchedText ;
126+
127+ // Find the base term from the glossary that matches.
128+ let baseTerm : string | undefined ;
129+
130+ if ( isJapaneseSite ) {
131+ // For Japanese, look for an exact match only.
132+ baseTerm = terms . find ( term =>
133+ actualMatch === term
134+ ) ;
135+ } else {
136+ // For English, check both singular and plural forms too.
137+ baseTerm = terms . find ( term =>
138+ actualMatch . toLowerCase ( ) === term . toLowerCase ( ) ||
139+ actualMatch . toLowerCase ( ) === `${ term . toLowerCase ( ) } s` ||
140+ actualMatch . toLowerCase ( ) === `${ term . toLowerCase ( ) } es`
141+ ) ;
142+ }
116143
117144 if ( ! baseTerm ) {
118145 // Skip if no matching base term found.
@@ -138,7 +165,8 @@ const GlossaryInjector: React.FC<GlossaryInjectorProps> = ({ children }) => {
138165 let textToUnderline = matchedText ;
139166 let suffix = '' ;
140167
141- if ( matchedText . toLowerCase ( ) !== baseTerm . toLowerCase ( ) ) {
168+ // Only apply pluralization logic for the English version of the site.
169+ if ( ! isJapaneseSite && matchedText . toLowerCase ( ) !== baseTerm . toLowerCase ( ) ) {
142170 // This is a plural form - only underline the base part.
143171 const baseTermLength = baseTerm . length ;
144172 textToUnderline = matchedText . substring ( 0 , baseTermLength ) ;
0 commit comments