291 lines
14 KiB
Go
291 lines
14 KiB
Go
package web
|
|
|
|
import (
|
|
"net/http"
|
|
"net/url"
|
|
"time"
|
|
)
|
|
|
|
type Locale string
|
|
|
|
const (
|
|
LocaleEnglish Locale = "en"
|
|
LocalePersian Locale = "fa"
|
|
localeCookie = "gl_locale"
|
|
)
|
|
|
|
var defaultTimezone = mustLoadLocation("Asia/Tehran")
|
|
|
|
func mustLoadLocation(name string) *time.Location {
|
|
location, err := time.LoadLocation(name)
|
|
if err != nil {
|
|
panic("load dashboard timezone: " + err.Error())
|
|
}
|
|
return location
|
|
}
|
|
|
|
func localeForRequest(response http.ResponseWriter, request *http.Request) Locale {
|
|
if locale, ok := validLocale(request.URL.Query().Get("lang")); ok {
|
|
http.SetCookie(response, &http.Cookie{
|
|
Name: localeCookie,
|
|
Value: string(locale),
|
|
Path: "/",
|
|
MaxAge: 365 * 24 * 60 * 60,
|
|
SameSite: http.SameSiteLaxMode,
|
|
})
|
|
return locale
|
|
}
|
|
if cookie, err := request.Cookie(localeCookie); err == nil {
|
|
if locale, ok := validLocale(cookie.Value); ok {
|
|
return locale
|
|
}
|
|
}
|
|
return LocaleEnglish
|
|
}
|
|
|
|
func validLocale(value string) (Locale, bool) {
|
|
switch Locale(value) {
|
|
case LocaleEnglish:
|
|
return LocaleEnglish, true
|
|
case LocalePersian:
|
|
return LocalePersian, true
|
|
default:
|
|
return "", false
|
|
}
|
|
}
|
|
|
|
func (l Locale) Direction() string {
|
|
if l == LocalePersian {
|
|
return "rtl"
|
|
}
|
|
return "ltr"
|
|
}
|
|
|
|
func localeURL(request *http.Request, locale Locale) string {
|
|
query := cloneQuery(request.URL.Query())
|
|
query.Set("lang", string(locale))
|
|
return request.URL.Path + "?" + query.Encode()
|
|
}
|
|
|
|
func cloneQuery(source url.Values) url.Values {
|
|
result := make(url.Values, len(source))
|
|
for key, values := range source {
|
|
result[key] = append([]string(nil), values...)
|
|
}
|
|
return result
|
|
}
|
|
|
|
func tr(locale Locale, key string) string {
|
|
if locale == LocalePersian {
|
|
if value, ok := persian[key]; ok {
|
|
return value
|
|
}
|
|
}
|
|
if value, ok := english[key]; ok {
|
|
return value
|
|
}
|
|
return key
|
|
}
|
|
|
|
var english = map[string]string{
|
|
"site_name": "DARANO",
|
|
"site_subtitle": "LEDGER NETWORK",
|
|
"overview": "Overview",
|
|
"transactions": "Transactions",
|
|
"assets": "Assets",
|
|
"accounts": "Accounts",
|
|
"read_only": "READ ONLY",
|
|
"dark_mode": "Use dark mode",
|
|
"light_mode": "Use light mode",
|
|
"general_ledger_explorer": "General ledger explorer",
|
|
"hero_line_one": "Every movement.",
|
|
"hero_line_two": "One durable record.",
|
|
"hero_description": "Inspect committed journals, trace blockchain transaction hashes, and reconstruct any ledger account without touching the write path.",
|
|
"transaction_placeholder": "Enter a transaction hash or journal ID",
|
|
"transaction_hash": "Transaction hash",
|
|
"explore_transaction": "Explore transaction",
|
|
"committed_journals": "Committed journals",
|
|
"ledger_entries": "Ledger entries",
|
|
"tracked_accounts": "Tracked accounts",
|
|
"last_recorded": "Last recorded",
|
|
"latest_activity": "Latest ledger activity",
|
|
"newest_first": "NEWEST FIRST",
|
|
"top_asset_holders": "Top asset holders",
|
|
"holder_balance_scope": "AVAILABLE + FROZEN · RECENT ASSETS",
|
|
"no_asset_holders": "No positive user holdings yet.",
|
|
"assets_explorer": "Asset explorer",
|
|
"track_asset_ownership": "Track asset ownership.",
|
|
"assets_description": "Review the leading positive user balances for the most recently active ledger assets.",
|
|
"rank": "Rank",
|
|
"holder": "Holder",
|
|
"balance": "Balance",
|
|
"holder_account": "Holder account",
|
|
"inspect_holder": "Inspect a holder.",
|
|
"holder_description": "This account combines the holder's available and frozen balances and activity for one asset.",
|
|
"combined_balance": "Combined balance",
|
|
"available_and_frozen": "AVAILABLE + FROZEN",
|
|
"holder_reference_invalid": "A holder identity and positive asset ID are required.",
|
|
"transaction": "Transaction",
|
|
"effect": "Effect",
|
|
"source": "Source",
|
|
"entries": "Entries",
|
|
"recorded": "Recorded",
|
|
"no_journals": "No committed journals yet.",
|
|
"network": "NETWORK",
|
|
"transaction_explorer": "Transaction explorer",
|
|
"trace_settlement": "Trace a settlement.",
|
|
"transaction_description": "Search an exact blockchain hash or internal journal ID retained on committed ledger journals.",
|
|
"transaction_not_found": "Transaction not found",
|
|
"transaction_missing": "No committed transaction matches that hash or journal ID.",
|
|
"transaction_lookup_error": "The transaction could not be loaded. Try again shortly.",
|
|
"enter_hash": "Enter a hash or journal ID to inspect its balanced financial effects.",
|
|
"latest_transactions": "Latest transactions",
|
|
"page": "PAGE",
|
|
"pagination": "Transaction pages",
|
|
"previous": "Previous",
|
|
"next": "Next",
|
|
"user_wallet": "User / wallet",
|
|
"user_wallet_placeholder": "Exact owner or wallet ID",
|
|
"effect_type": "Effect type",
|
|
"effect_type_placeholder": "Exact effect type",
|
|
"apply_filters": "Apply filters",
|
|
"clear_filters": "Clear",
|
|
"committed": "COMMITTED",
|
|
"journal_id": "Journal ID",
|
|
"ledger_sequence": "Ledger sequence",
|
|
"balanced_entries": "Balanced entries",
|
|
"asset": "Asset",
|
|
"internal": "internal",
|
|
"system": "system",
|
|
"account_explorer": "Account explorer",
|
|
"rebuild_account": "Rebuild an account.",
|
|
"account_description": "Select the stable ledger identity and asset to calculate its current balance from immutable entries.",
|
|
"account_class": "Account class",
|
|
"owner_type": "Owner type",
|
|
"owner_id": "Owner ID",
|
|
"stable_owner_id": "Stable owner ID",
|
|
"asset_id": "Asset ID",
|
|
"explore": "Explore",
|
|
"account_unavailable": "Account unavailable",
|
|
"asset_positive": "Asset ID must be a positive integer.",
|
|
"account_lookup_error": "The account could not be loaded. Check its identity and try again.",
|
|
"ledger_identity": "Ledger identity",
|
|
"current_balance": "Current balance",
|
|
"account_activity": "Account activity",
|
|
"journals": "JOURNALS",
|
|
"choose_account": "Choose an account class, owner, and asset to begin.",
|
|
"explorer_error": "Explorer error",
|
|
"dashboard_unavailable": "Dashboard unavailable",
|
|
"assets_unavailable": "Assets unavailable",
|
|
"transactions_unavailable": "Transactions unavailable",
|
|
"read_model_unavailable": "The ledger read model could not be reached. Try again shortly.",
|
|
"footer_description": "Darano General Ledger · immutable financial history",
|
|
"timezone_notice": "All times shown in Asia/Tehran",
|
|
"title_overview": "Network overview",
|
|
"title_transactions": "Transaction explorer",
|
|
"title_assets": "Asset explorer",
|
|
"title_accounts": "Account explorer",
|
|
"title_holder": "Holder account",
|
|
}
|
|
|
|
var persian = map[string]string{
|
|
"site_name": "دارانو",
|
|
"site_subtitle": "شبکه دفتر کل",
|
|
"overview": "نمای کلی",
|
|
"transactions": "تراکنشها",
|
|
"assets": "داراییها",
|
|
"accounts": "حسابها",
|
|
"read_only": "فقط خواندنی",
|
|
"dark_mode": "استفاده از حالت تیره",
|
|
"light_mode": "استفاده از حالت روشن",
|
|
"general_ledger_explorer": "کاوشگر دفتر کل",
|
|
"hero_line_one": "هر جابهجایی.",
|
|
"hero_line_two": "یک سابقه ماندگار.",
|
|
"hero_description": "دفاتر ثبتشده را ببینید، هش تراکنشهای بلاکچین را ردیابی کنید و هر حساب دفتر کل را بدون دسترسی به مسیر نوشتن بازسازی کنید.",
|
|
"transaction_placeholder": "هش تراکنش یا شناسه دفتر را وارد کنید",
|
|
"transaction_hash": "هش تراکنش",
|
|
"explore_transaction": "جستوجوی تراکنش",
|
|
"committed_journals": "دفاتر ثبتشده",
|
|
"ledger_entries": "ردیفهای دفتر کل",
|
|
"tracked_accounts": "حسابهای ردیابیشده",
|
|
"last_recorded": "آخرین ثبت",
|
|
"latest_activity": "آخرین فعالیت دفتر کل",
|
|
"newest_first": "جدیدترین ابتدا",
|
|
"top_asset_holders": "دارندگان برتر دارایی",
|
|
"holder_balance_scope": "در دسترس + مسدود · داراییهای اخیر",
|
|
"no_asset_holders": "هنوز موجودی مثبت کاربری ثبت نشده است.",
|
|
"assets_explorer": "کاوشگر دارایی",
|
|
"track_asset_ownership": "مالکیت دارایی را ردیابی کنید.",
|
|
"assets_description": "بالاترین موجودیهای مثبت کاربران را برای داراییهای فعال اخیر دفتر کل بررسی کنید.",
|
|
"rank": "رتبه",
|
|
"holder": "دارنده",
|
|
"balance": "موجودی",
|
|
"holder_account": "حساب دارنده",
|
|
"inspect_holder": "دارنده را بررسی کنید.",
|
|
"holder_description": "این حساب موجودی و فعالیت در دسترس و مسدود دارنده را برای یک دارایی ترکیب میکند.",
|
|
"combined_balance": "موجودی ترکیبی",
|
|
"available_and_frozen": "در دسترس + مسدود",
|
|
"holder_reference_invalid": "شناسه دارنده و شناسه مثبت دارایی الزامی است.",
|
|
"transaction": "تراکنش",
|
|
"effect": "اثر",
|
|
"source": "منبع",
|
|
"entries": "ردیفها",
|
|
"recorded": "زمان ثبت",
|
|
"no_journals": "هنوز دفتری ثبت نشده است.",
|
|
"network": "شبکه",
|
|
"transaction_explorer": "کاوشگر تراکنش",
|
|
"trace_settlement": "تسویه را ردیابی کنید.",
|
|
"transaction_description": "هش دقیق بلاکچین یا شناسه دفتر داخلی را در دفاتر قطعی جستوجو کنید.",
|
|
"transaction_not_found": "تراکنش پیدا نشد",
|
|
"transaction_missing": "هیچ تراکنش قطعی با این هش یا شناسه دفتر پیدا نشد.",
|
|
"transaction_lookup_error": "بارگذاری تراکنش ممکن نشد. کمی بعد دوباره تلاش کنید.",
|
|
"enter_hash": "برای مشاهده اثرهای مالی تراز، هش یا شناسه دفتر را وارد کنید.",
|
|
"latest_transactions": "آخرین تراکنشها",
|
|
"page": "صفحه",
|
|
"pagination": "صفحههای تراکنش",
|
|
"previous": "قبلی",
|
|
"next": "بعدی",
|
|
"user_wallet": "کاربر / کیف پول",
|
|
"user_wallet_placeholder": "شناسه دقیق مالک یا کیف پول",
|
|
"effect_type": "نوع اثر",
|
|
"effect_type_placeholder": "نوع دقیق اثر",
|
|
"apply_filters": "اعمال فیلترها",
|
|
"clear_filters": "پاککردن",
|
|
"committed": "ثبتشده",
|
|
"journal_id": "شناسه دفتر",
|
|
"ledger_sequence": "شماره دفتر",
|
|
"balanced_entries": "ردیفهای تراز",
|
|
"asset": "دارایی",
|
|
"internal": "داخلی",
|
|
"system": "سیستم",
|
|
"account_explorer": "کاوشگر حساب",
|
|
"rebuild_account": "یک حساب را بازسازی کنید.",
|
|
"account_description": "شناسه پایدار حساب و دارایی را انتخاب کنید تا موجودی فعلی از ردیفهای تغییرناپذیر محاسبه شود.",
|
|
"account_class": "نوع حساب",
|
|
"owner_type": "نوع مالک",
|
|
"owner_id": "شناسه مالک",
|
|
"stable_owner_id": "شناسه پایدار مالک",
|
|
"asset_id": "شناسه دارایی",
|
|
"explore": "جستوجو",
|
|
"account_unavailable": "حساب در دسترس نیست",
|
|
"asset_positive": "شناسه دارایی باید یک عدد صحیح مثبت باشد.",
|
|
"account_lookup_error": "بارگذاری حساب ممکن نشد. شناسه آن را بررسی و دوباره تلاش کنید.",
|
|
"ledger_identity": "شناسه دفتر کل",
|
|
"current_balance": "موجودی فعلی",
|
|
"account_activity": "فعالیت حساب",
|
|
"journals": "دفتر",
|
|
"choose_account": "برای شروع، نوع حساب، مالک و دارایی را انتخاب کنید.",
|
|
"explorer_error": "خطای کاوشگر",
|
|
"dashboard_unavailable": "داشبورد در دسترس نیست",
|
|
"assets_unavailable": "داراییها در دسترس نیستند",
|
|
"transactions_unavailable": "تراکنشها در دسترس نیستند",
|
|
"read_model_unavailable": "مدل خواندنی دفتر کل در دسترس نیست. کمی بعد دوباره تلاش کنید.",
|
|
"footer_description": "دفتر کل دارانو · تاریخچه مالی تغییرناپذیر",
|
|
"timezone_notice": "همه زمانها بر پایه منطقه زمانی تهران نمایش داده میشوند",
|
|
"title_overview": "نمای کلی شبکه",
|
|
"title_transactions": "کاوشگر تراکنش",
|
|
"title_assets": "کاوشگر دارایی",
|
|
"title_accounts": "کاوشگر حساب",
|
|
"title_holder": "حساب دارنده",
|
|
}
|