i18n: sync translation files with current .pot template (#173)#186
i18n: sync translation files with current .pot template (#173)#186parhumm merged 2 commits intodevelopmentfrom
Conversation
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (25)
📝 WalkthroughWalkthroughA new Playwright end-to-end test suite validates internationalization catalog sync for issue Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ccca279 to
518e876
Compare
|
Deep standards pass on this PR found a few issues that should be fixed before merge.
I re-ran |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (5)
tests/e2e/i18n-catalog-sync.spec.ts (5)
12-12: Unused import:BASE_URL.
BASE_URLis imported but never used—page.goto()calls use relative URLs. Either remove the import or useBASE_URLexplicitly for clarity.-import { BASE_URL, MYSQL_CONFIG } from './helpers/env'; +import { MYSQL_CONFIG } from './helpers/env';🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/e2e/i18n-catalog-sync.spec.ts` at line 12, Remove the unused import BASE_URL from the top import list (currently importing BASE_URL, MYSQL_CONFIG) or alternatively update the page navigation calls (page.goto) to use BASE_URL so the import is actually used; reference the import symbol BASE_URL and the test navigation calls like page.goto to decide whether to delete the import or switch to absolute URLs.
41-46: Consider typing the MySQL result instead ofas any.+interface WpOption { + option_value: string; +} + async function getWplang(): Promise<string> { - const [rows] = await pool.execute( + const [rows] = await pool.execute<mysql.RowDataPacket[]>( "SELECT option_value FROM wp_options WHERE option_name = 'WPLANG'" - ) as any; - return rows.length > 0 ? rows[0].option_value : ''; + ); + return rows.length > 0 ? (rows[0] as WpOption).option_value : ''; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/e2e/i18n-catalog-sync.spec.ts` around lines 41 - 46, getWplang currently casts the result of pool.execute to any; replace that with a proper MySQL result type so the row shape is typed. Use the mysql2 types (e.g. import RowDataPacket from 'mysql2' or use the pool.execute generic) and cast the execute call to something like [RowDataPacket[]] or pool.execute<RowDataPacket[]>("...") so rows is typed and rows[0].option_value is checked safely inside getWplang.
55-59: Add defensive check inafterAllfor pool initialization failure.If
beforeAllfails to create the pool,afterAllwill throw when accessingpool. A defensive check prevents cascading errors.test.afterAll(async () => { + if (!pool) return; // Restore locale to en_US await pool.execute("UPDATE wp_options SET option_value = '' WHERE option_name = 'WPLANG'"); await pool.end(); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/e2e/i18n-catalog-sync.spec.ts` around lines 55 - 59, The afterAll teardown references the database connection variable pool and will throw if beforeAll failed to initialize it; update the test.afterAll block to defensively check that pool is defined/non-null (and optionally that pool.execute/end are functions) before calling pool.execute(...) and pool.end(), so guard the existing UPDATE and end() calls with an if (pool) or equivalent check to avoid cascading errors from a failed beforeAll initialization.
103-106: Consider strengthening translation assertions.Checking for "at least one" German translation is lenient and could pass even if most translations are broken. If the goal is to verify comprehensive translation loading, consider checking for multiple distinct translated strings.
- expect( - hasGermanTracker || hasGermanEnable || hasGermanSettings, - `Expected at least one German translation. Page text snippet: ${bodyText!.substring(0, 500)}` - ).toBeTruthy(); + // Require at least two distinct translations to ensure catalog loaded properly + const translationCount = [hasGermanTracker, hasGermanEnable, hasGermanSettings].filter(Boolean).length; + expect( + translationCount, + `Expected multiple German translations but found ${translationCount}. Page text: ${bodyText!.substring(0, 500)}` + ).toBeGreaterThanOrEqual(2);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/e2e/i18n-catalog-sync.spec.ts` around lines 103 - 106, The current assertion only requires a single German translation (hasGermanTracker || hasGermanEnable || hasGermanSettings) which is too weak; update the test to assert that multiple distinct translated strings are present by counting truthy flags (hasGermanTracker, hasGermanEnable, hasGermanSettings, and any additional German checks you add) and expecting the count to be >= 2 (or another threshold), preserving the diagnostic message using bodyText!.substring(0,500) so failures still show the page snippet.
90-90: ReplacewaitForTimeoutwith explicit wait conditions.
waitForTimeoutis a Playwright anti-pattern—it's flaky and slows tests unnecessarily. Wait for a specific element or network idle instead.- await page.waitForTimeout(2000); // settle + // Wait for a known element to be visible + await page.locator('text=SlimStat').first().waitFor({ state: 'visible', timeout: 10_000 });Apply the same pattern to lines 118, 144, and 170.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/e2e/i18n-catalog-sync.spec.ts` at line 90, Replace each instance of await page.waitForTimeout(2000); with an explicit wait for the specific condition that indicates the app is ready: use await page.waitForSelector('<expected-selector>') for DOM changes, or await page.waitForResponse(resp => resp.url().includes('<api-endpoint>') && resp.status() === 200) when waiting for network results, or await page.waitForLoadState('networkidle') when waiting for background requests to finish; update the four occurrences of page.waitForTimeout(2000) in this test (search for the exact call string) and choose the appropriate selector or response predicate that matches the action immediately before/after each call (or use Promise.all([page.waitForResponse(...), page.click(...)]) when the wait should follow a click).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@tests/e2e/i18n-catalog-sync.spec.ts`:
- Around line 20-24: The dbConfig object overrides MYSQL_CONFIG with a hardcoded
machine-specific socketPath which breaks CI/other developers; remove that
hardcoded path and rely on MYSQL_CONFIG (and the existing MYSQL_SOCKET env var)
instead—update the dbConfig declaration (the object named dbConfig and its
socketPath property) to stop injecting '/Users/parhumm/...' and either omit
socketPath entirely or only set it from process.env.MYSQL_SOCKET so local
overrides come from the environment.
- Around line 179-181: The negative test assertion using
expect(htmlContent).not.toContain('Warning:') is too broad and may flag
legitimate UI copy; update the assertion to search for a more specific warning
pattern (e.g., a runtime stack/trace) by checking htmlContent for a regex like a
"Warning:" followed by a newline and an "at " stack frame or a file path (for
example use a regexp that matches /Warning:.*\n\s+at / or
/Warning:.*(node_modules|webpack)/) instead of the plain 'Warning:' string;
replace the expect(htmlContent).not.toContain('Warning:') call with an assertion
that htmlContent does not match that specific regexp so only actual runtime
warnings with stack traces are caught.
- Around line 30-46: The queries in setWplang, getWplang, and the afterAll
cleanup use the hardcoded table name "wp_options", which will break for installs
with a custom table prefix; read a table prefix from config/env (e.g.,
process.env.WP_DB_PREFIX or a shared test config constant, defaulting to "wp_"
if unset), compute the options table name as `${prefix}options`, and use that
variable in the SQL strings for pool.execute in setWplang, getWplang, and the
cleanup query so all calls target the correct table across environments.
---
Nitpick comments:
In `@tests/e2e/i18n-catalog-sync.spec.ts`:
- Line 12: Remove the unused import BASE_URL from the top import list (currently
importing BASE_URL, MYSQL_CONFIG) or alternatively update the page navigation
calls (page.goto) to use BASE_URL so the import is actually used; reference the
import symbol BASE_URL and the test navigation calls like page.goto to decide
whether to delete the import or switch to absolute URLs.
- Around line 41-46: getWplang currently casts the result of pool.execute to
any; replace that with a proper MySQL result type so the row shape is typed. Use
the mysql2 types (e.g. import RowDataPacket from 'mysql2' or use the
pool.execute generic) and cast the execute call to something like
[RowDataPacket[]] or pool.execute<RowDataPacket[]>("...") so rows is typed and
rows[0].option_value is checked safely inside getWplang.
- Around line 55-59: The afterAll teardown references the database connection
variable pool and will throw if beforeAll failed to initialize it; update the
test.afterAll block to defensively check that pool is defined/non-null (and
optionally that pool.execute/end are functions) before calling pool.execute(...)
and pool.end(), so guard the existing UPDATE and end() calls with an if (pool)
or equivalent check to avoid cascading errors from a failed beforeAll
initialization.
- Around line 103-106: The current assertion only requires a single German
translation (hasGermanTracker || hasGermanEnable || hasGermanSettings) which is
too weak; update the test to assert that multiple distinct translated strings
are present by counting truthy flags (hasGermanTracker, hasGermanEnable,
hasGermanSettings, and any additional German checks you add) and expecting the
count to be >= 2 (or another threshold), preserving the diagnostic message using
bodyText!.substring(0,500) so failures still show the page snippet.
- Line 90: Replace each instance of await page.waitForTimeout(2000); with an
explicit wait for the specific condition that indicates the app is ready: use
await page.waitForSelector('<expected-selector>') for DOM changes, or await
page.waitForResponse(resp => resp.url().includes('<api-endpoint>') &&
resp.status() === 200) when waiting for network results, or await
page.waitForLoadState('networkidle') when waiting for background requests to
finish; update the four occurrences of page.waitForTimeout(2000) in this test
(search for the exact call string) and choose the appropriate selector or
response predicate that matches the action immediately before/after each call
(or use Promise.all([page.waitForResponse(...), page.click(...)]) when the wait
should follow a click).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: fbea612a-25f1-4df3-ba7d-413afa5b480e
📒 Files selected for processing (25)
languages/wp-slimstat-bel.molanguages/wp-slimstat-bel.polanguages/wp-slimstat-de_DE.molanguages/wp-slimstat-de_DE.polanguages/wp-slimstat-fa_IR.molanguages/wp-slimstat-fa_IR.polanguages/wp-slimstat-fr_CA.molanguages/wp-slimstat-fr_CA.polanguages/wp-slimstat-fr_FR.molanguages/wp-slimstat-fr_FR.polanguages/wp-slimstat-id_ID.molanguages/wp-slimstat-id_ID.polanguages/wp-slimstat-ja.molanguages/wp-slimstat-ja.polanguages/wp-slimstat-pl_PL.molanguages/wp-slimstat-pl_PL.polanguages/wp-slimstat-ru_RU.molanguages/wp-slimstat-ru_RU.polanguages/wp-slimstat-sv_SE.molanguages/wp-slimstat-sv_SE.polanguages/wp-slimstat-tr_TR.molanguages/wp-slimstat-tr_TR.polanguages/wp-slimstat-zh_CN.molanguages/wp-slimstat-zh_CN.potests/e2e/i18n-catalog-sync.spec.ts
tests/e2e/i18n-catalog-sync.spec.ts
Outdated
| // Use the correct MySQL socket for Local by Flywheel | ||
| const dbConfig = { | ||
| ...MYSQL_CONFIG, | ||
| socketPath: process.env.MYSQL_SOCKET || '/Users/parhumm/Library/Application Support/Local/run/X-JdmZXIa/mysql/mysqld.sock', | ||
| }; |
There was a problem hiding this comment.
Hardcoded developer-local socket path breaks CI and other environments.
The socketPath override contains a machine-specific path (/Users/parhumm/...) that will fail for other developers and in CI. The MYSQL_CONFIG from helpers/env.ts already handles environment-based configuration properly.
Proposed fix: Remove the local override
-// Use the correct MySQL socket for Local by Flywheel
-const dbConfig = {
- ...MYSQL_CONFIG,
- socketPath: process.env.MYSQL_SOCKET || '/Users/parhumm/Library/Application Support/Local/run/X-JdmZXIa/mysql/mysqld.sock',
-};
+const dbConfig = MYSQL_CONFIG;If a local override is needed during development, set the MYSQL_SOCKET environment variable instead.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Use the correct MySQL socket for Local by Flywheel | |
| const dbConfig = { | |
| ...MYSQL_CONFIG, | |
| socketPath: process.env.MYSQL_SOCKET || '/Users/parhumm/Library/Application Support/Local/run/X-JdmZXIa/mysql/mysqld.sock', | |
| }; | |
| const dbConfig = MYSQL_CONFIG; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@tests/e2e/i18n-catalog-sync.spec.ts` around lines 20 - 24, The dbConfig
object overrides MYSQL_CONFIG with a hardcoded machine-specific socketPath which
breaks CI/other developers; remove that hardcoded path and rely on MYSQL_CONFIG
(and the existing MYSQL_SOCKET env var) instead—update the dbConfig declaration
(the object named dbConfig and its socketPath property) to stop injecting
'/Users/parhumm/...' and either omit socketPath entirely or only set it from
process.env.MYSQL_SOCKET so local overrides come from the environment.
- Merge wp-slimstat.pot into all 12 .po files using msgmerge - Remove fuzzy translations to prevent placeholder/URL/HTML mismatches - Remove obsolete #~ entries with msgattrib - Rebuild .mo binary files with msgfmt --check --check-format Fuzzy translations are removed because they can contain: - Mismatched %s/%d placeholders breaking sprintf() calls - Outdated URLs that don't match source strings - Malformed HTML markup Untranslated strings will fall back to English, which is safer than displaying broken placeholders or incorrect URLs.
b511d72 to
dab1d44
Compare
E2E QA Results — Issue #173: i18n Catalog SyncBranch: Catalog Verification
Playwright E2E Tests — 5/5 Passing
Translation Coverage (informational — not a blocker)
Verdict✅ Ready to merge — catalog sync verified, translations load correctly per locale, graceful fallback confirmed, no regressions. 🤖 Generated with Claude Code |
- Remove hardcoded Local by Flywheel socket path, use MYSQL_CONFIG from env - Use configurable WP_DB_PREFIX for table names instead of hardcoded wp_ - Type DB queries with RowDataPacket instead of `as any` - Guard afterAll teardown against uninitialized pool - Remove unused BASE_URL import - Narrow Warning assertion to match PHP file paths, not UI copy - Document fuzzy-string limitation in German translation assertion
All language files now contain the current 1,438 message strings, enabling proper localization support for new features.
Describe your changes
...
Submission Review Guidelines:
CHANGELOG.md.Type of change
Summary by CodeRabbit