feat: Thai language for every customization

- translations/th.csv: custom field labels, messages, print format and
  letter head text, the 22 Tax Withholding Category names; overrides the
  upstream Thai for the standard labels the print formats show
- print formats embed Sarabun (public/fonts, OFL) so PDFs render Thai on
  servers without a Thai font
- letter head labels go through _()
- withholding row description is translated when stored
- in_words: Thai "...บาทถ้วน" wording via num2words when the language is
  Thai (ThaiSalesInvoice.set_total_in_words); print formats re-derive it
  in the print language (get_in_words)
- fixture `modified` bumped so migrate re-imports the changed documents
This commit is contained in:
2026-09-15 06:50:55 +00:00
parent 33310c51ae
commit 9a8602f74e
10 changed files with 204 additions and 9 deletions
+15 -1
View File
@@ -10,6 +10,8 @@ from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category
from frappe import _
from frappe.utils import cint, flt
from default_thai_company.utils import money_in_words
# Liability: tax we withhold from suppliers and remit on P.N.D.3/53 (linked on every category).
# Asset: tax customers withhold from us, creditable against corporate income tax.
LIABILITY_ACCOUNT = "Withholding Tax Payable"
@@ -158,6 +160,17 @@ class ThaiSalesInvoice(SalesInvoice):
self.precision("amount_after_withholding"),
)
def set_total_in_words(self):
"""SellingController's version, with Thai wording when the saving user's
language is Thai. Print formats re-derive the text per print language
(`get_in_words`)."""
base_amount = abs(
self.base_grand_total if self.is_rounded_total_disabled() else self.base_rounded_total
)
self.base_in_words = money_in_words(base_amount, self.company_currency)
amount = abs(self.grand_total if self.is_rounded_total_disabled() else self.rounded_total)
self.in_words = money_in_words(amount, self.currency)
class ThaiPaymentEntry(PaymentEntry):
def build_gl_map(self):
@@ -333,7 +346,8 @@ def get_customer_withholding(doc):
total += withholding_on(details_by_category[category], base_taxable, base_taxable, precision)
if len(details_by_category) == 1:
description = next(iter(details_by_category.values())).description
# category_name; translations/th.csv carries the fixture categories
description = _(next(iter(details_by_category.values())).description)
else:
description = _("Withholding tax deducted by customer")
return flt(total, precision), description