<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Mytrade.kz Engineering]]></title><description><![CDATA[Practical technical notes from Mytrade.kz on multilingual e-commerce, product data, prices and currencies, units, localization, accessibility and quality assura]]></description><link>https://mytrade.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sun, 01 Nov 2026 11:10:20 GMT</lastBuildDate><atom:link href="https://mytrade.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to Test Multilingual Product Listings: Prices, Currencies, Units and Translation Errors]]></title><description><![CDATA[By the Mytrade team A translated product title can look correct while the order is wrong. A comma may change the interpreted amount, a unit may describe…]]></description><link>https://mytrade.hashnode.dev/how-to-test-multilingual-product-listings-prices-currencies-units-and-translation-errors</link><guid isPermaLink="true">https://mytrade.hashnode.dev/how-to-test-multilingual-product-listings-prices-currencies-units-and-translation-errors</guid><category><![CDATA[localization]]></category><category><![CDATA[Testing]]></category><category><![CDATA[ecommerce]]></category><dc:creator><![CDATA[Mytrade.kz]]></dc:creator><pubDate>Wed, 21 Oct 2026 15:26:06 GMT</pubDate><content:encoded><![CDATA[<p>By the Mytrade team</p>
<p>A translated product title can look correct while the order is wrong. A comma may change the interpreted amount, a unit may describe the package instead of one item, or a model identifier may be altered during translation.</p>
<p>This checklist is prepared by <a href="https://mytrade.kz">Mytrade.kz</a> for developers and QA teams working on multilingual product listings. All products, amounts and exchange rates below are synthetic test fixtures. They are not findings from an audit of Mytrade or claims about production behavior. This article was prepared with AI assistance.</p>
<h2>1. Start with a fixture that separates meaning from presentation</h2>
<p>Keep the product identity, money and physical quantities independent of translated labels. For example:</p>
<pre><code class="language-json">{
  "sku": "TEST-00042",
  "model": "AX-1500B",
  "price": { "minorUnits": 123456, "currency": "EUR", "scale": 2 },
  "netWeight": { "value": "1.5", "unit": "kg" },
  "itemsPerPack": 6,
  "title": {
    "en": "AX-1500B replacement filter, pack of 6",
    "de": "AX-1500B Ersatzfilter, 6er-Pack"
  }
}
</code></pre>
<p>Here, 123456 minor units with scale 2 means EUR 1234.56. The scale belongs to this fixture; do not assume every currency uses two decimal places. Decide whether the weight describes one filter or the entire pack, and encode that distinction explicitly.</p>
<p>Build a small matrix before testing:</p>
<ul>
<li><p>Language: English, German, French, Russian, Kazakh and Arabic where supported.</p>
</li>
<li><p>Currency: EUR, USD, KZT and a zero-decimal currency such as JPY.</p>
</li>
<li><p>Viewport: narrow mobile and desktop; include text zoom.</p>
</li>
<li><p>State: listing, product detail, cart, checkout and order confirmation.</p>
</li>
</ul>
<p>Language, region, currency and shipping destination are separate inputs. An English interface does not imply USD, and an Arabic interface does not determine the shipping country.</p>
<h2>2. Reproduce number and currency formatting</h2>
<p>Run the following JavaScript in a browser console or save it as format-check.js and run it with Node.js. It prints the runtime's formatting, structured parts and Unicode code points so invisible spacing is inspectable.</p>
<pre><code class="language-javascript">const amount = 1234.56;

for (const locale of ["en-US", "de-DE", "fr-FR", "ru-RU", "kk-KZ", "ar-EG"]) {
  const formatter = new Intl.NumberFormat(locale, {
    style: "currency",
    currency: "EUR",
    currencyDisplay: "code",
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  });
  const text = formatter.format(amount);
  console.log(locale, JSON.stringify(text));
  console.log(formatter.formatToParts(amount));
  console.log(Array.from(text, c =&gt;
    `U+${c.codePointAt(0).toString(16).toUpperCase().padStart(4, "0")}`
  ).join(" "));
}
</code></pre>
<p>The English US presentation normally uses a comma for grouping and a period for decimals; German uses the opposite. French commonly includes a narrow non-breaking space for grouping. Exact spacing, direction marks and locale data can differ between runtime versions. Record the browser or Node version and the resolved locale when reporting a difference. Pin the runtime when using exact string snapshots.</p>
<p>Check that:</p>
<ul>
<li><p>The numeric value and ISO currency remain unchanged when only the display locale changes.</p>
</li>
<li><p>The amount and currency do not separate awkwardly across lines.</p>
</li>
<li><p>Fraction digits follow the currency and your documented display policy. Test JPY separately rather than forcing the fixture's two digits on every currency.</p>
</li>
<li><p>Zero, fractions below one, large amounts and refund values render correctly. Missing prices must not silently become zero.</p>
</li>
<li><p>Ambiguous symbols such as "$" have enough context to distinguish USD from other dollar currencies.</p>
</li>
</ul>
<p>Do not use parseFloat on localized user input:</p>
<pre><code class="language-javascript">console.log(parseFloat("1.234,56")); // 1.234, not 1234.56
console.log(parseFloat("1,234.56")); // 1, not 1234.56
</code></pre>
<p>Intl.NumberFormat is a formatter, not a general localized-number parser. Define accepted input formats, validate the entire input and convert to a canonical representation. Include regular spaces, non-breaking spaces, Arabic digits, pasted currency codes and invalid mixed separators in input tests. Reject ambiguous input with a useful message instead of guessing.</p>
<h2>3. Test translation and conversion as different operations</h2>
<p>Translation changes labels and presentation. Currency conversion changes a monetary value using a defined rate. Switching the interface from English to German must not itself convert EUR into another currency unless that is an explicit product requirement.</p>
<p>For a deterministic conversion test, use a fixed fake rate:</p>
<ul>
<li><p>Source: EUR 10.00.</p>
</li>
<li><p>Synthetic rate: 1 EUR = 500 KZT. This is a test rate, not a market quote.</p>
</li>
<li><p>Expected converted amount: KZT 5000, before any explicitly modeled fees.</p>
</li>
</ul>
<p>Record the source and target currencies, rate identifier, timestamp and rounding policy in the test evidence. Use decimal arithmetic or an equivalent exact-money design for business calculations. Formatting should happen after the calculation.</p>
<p>Compare line-level and order-level rounding with three synthetic items at EUR 0.01 and a fake factor of 1.5 into a currency displayed with two fractional digits. Under half-up rounding, each converted item rounds from 0.015 to 0.02, totaling 0.06. Converting the 0.03 subtotal first produces 0.045, rounded to 0.05. Neither strategy should be chosen accidentally: document the intended policy and test the backend against it.</p>
<p>When a quote expires or a rate changes, the customer must see the new total and confirm it before submission. The server must validate the amount; a formatted string from the browser is not an authoritative price.</p>
<h2>4. Keep units and package quantities explicit</h2>
<p>Translation of "kg" does not convert a measurement. Test the quantity, unit, scope and conversion together:</p>
<ul>
<li><p>1.5 kg remains the same mass when displayed as 1,5 kg in a locale using a decimal comma.</p>
</li>
<li><p>If pounds are supported, 1.5 kg is approximately 3.30693 lb; show precision appropriate to the product rather than all computed digits.</p>
</li>
<li><p>A pack of six must not become six kilograms. Distinguish price per item, per pack and per kilogram.</p>
</li>
<li><p>For dimensions, preserve labeled axes: length 20 cm, width 10 cm, height 5 cm. Translating the labels must not swap them.</p>
</li>
<li><p>Preserve squared and cubed units: m² and m³ are different quantities. Test superscripts in search, exports and confirmation documents.</p>
</li>
<li><p>Avoid ambiguous abbreviations such as "oz" without specifying whether the field is mass or volume; US and Imperial fluid ounces also differ.</p>
</li>
</ul>
<p>Compare the display against canonical data and a separately calculated expected conversion. Do not use a formatter as the only oracle for both implementation and test.</p>
<h2>5. Protect identifiers and translation meaning</h2>
<p>Mark SKUs, model identifiers, part numbers and serial numbers as non-translatable. Assert exact equality for AX-1500B across every language and every order step. Preserve leading zeros in identifiers such as 00042 by treating them as strings.</p>
<p>Include these cases in a terminology review:</p>
<ul>
<li><p>Latin A versus Cyrillic А: visually similar characters can identify different strings.</p>
</li>
<li><p>"Compatible with AX-1500B" versus "manufactured by AX": compatibility is not manufacturer identity.</p>
</li>
<li><p>"Not included", "used", "refurbished" and "minimum order": losing a negative or qualifier changes the offer.</p>
</li>
<li><p>"From EUR 10" versus "EUR 10": a starting price is not a fixed quote.</p>
</li>
<li><p>Singular and plural at 0, 1, 2 and other values required by each supported language.</p>
</li>
<li><p>Untranslated placeholders such as {count}, raw translation keys and fallback text in a different language.</p>
</li>
</ul>
<p>Have a qualified speaker review high-risk descriptions and purchasing instructions. Automated checks can detect missing strings and altered identifiers, but cannot establish that a translation preserves the commercial meaning.</p>
<h2>6. Exercise encoding, long text and right-to-left layouts</h2>
<p>Create a fixture containing Kazakh characters ә, ғ, қ, ң, ө, ұ, ү, һ, і; Cyrillic; Arabic; an accented character; a multiplication sign; and an emoji. Check the full path through API responses, storage, page rendering, search, CSV export and order messages. Inspect replacement characters such as �, mojibake and characters that disappear after saving.</p>
<p>Unicode normalization needs a documented policy. For ordinary searchable text, compare composed "é" with "e" followed by a combining acute accent. Do not normalize identifiers blindly if the source system treats their code points as significant.</p>
<p>For long text, use realistic translations plus a deliberately expanded fixture. Test an unbroken identifier, a multi-line title, long unit labels and validation messages at narrow widths and 200% text zoom. Essential specifications, price qualifiers and the final action must remain readable. If a title is truncated, provide access to its full text.</p>
<p>For an Arabic product page, set the page direction deliberately and isolate embedded identifiers:</p>
<pre><code class="language-html">&lt;section lang="ar" dir="rtl"&gt;
  &lt;p&gt;رقم الطراز: &lt;bdi dir="ltr"&gt;AX-1500B&lt;/bdi&gt;&lt;/p&gt;
  &lt;p&gt;المنتج: &lt;bdi dir="auto"&gt;Replacement filter&lt;/bdi&gt;&lt;/p&gt;
&lt;/section&gt;
</code></pre>
<p>Use the locale formatter for price text and inspect the result in the RTL context. Test brackets, slashes, minus signs, selection, copy/paste and keyboard navigation. Use CSS logical properties where appropriate. Review directional icons individually: not every icon should be mirrored.</p>
<p>W3C recommends markup for directionality when HTML is available. Invisible Unicode direction controls may appear in formatted output; do not strip them globally as a cosmetic cleanup. Investigate unexpected controls in user-supplied identifiers separately.</p>
<h2>7. Reconcile the final order</h2>
<p>Use a sandbox checkout or a test order flow. Before the customer confirms, compare the selected variant, model, quantity, package size, currency, item prices, shipping, tax, discounts and final total against the server's quote. Then compare the accepted order record and confirmation message against the exact quote accepted by the customer.</p>
<p>Check these transitions explicitly:</p>
<ul>
<li><p>Switch the language after adding the item to the cart.</p>
</li>
<li><p>Change the display currency, then return to the original one.</p>
</li>
<li><p>Change quantity and shipping destination.</p>
</li>
<li><p>Refresh the page and restore the cart.</p>
</li>
<li><p>Reopen an expired quote.</p>
</li>
<li><p>Test a failed submission and retry without creating a duplicate order.</p>
</li>
</ul>
<p>If an exchange rate, stock condition or shipping charge changes the offer, require a clear updated review before order submission. A confirmation must not silently display a different currency or total from the accepted order. Localized dates should also make the delivery window unambiguous.</p>
<h2>8. Capture evidence that another engineer can reproduce</h2>
<p>For each failure, record the fixture ID, build, browser/runtime, locale, currency, viewport, exact steps, expected result and actual result. Include canonical API values as well as the rendered text. Capture Unicode code points when the issue involves spacing or direction. Redact customer data and credentials.</p>
<p>A useful release gate is concrete: identifiers remain intact; prices and units preserve meaning; approved conversions and rounding match the server; critical text remains usable; and the accepted order matches the confirmation in every supported locale. A translated screen is ready only when the customer can verify the same product and commercial terms from listing to confirmation.</p>
<h2>Technical references</h2>
<ul>
<li><p><a href="https://tc39.es/ecma402/#sec-intl.numberformat">ECMAScript Internationalization API, Intl.NumberFormat</a></p>
</li>
<li><p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat">MDN, Intl.NumberFormat and formatToParts</a></p>
</li>
<li><p><a href="https://www.w3.org/International/articles/inline-bidi-markup/">W3C, Inline markup and bidirectional text in HTML</a></p>
</li>
<li><p><a href="https://www.w3.org/International/questions/qa-bidi-unicode-controls">W3C, Unicode controls for bidirectional text</a></p>
</li>
</ul>
]]></content:encoded></item></channel></rss>