欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Singleton之我见(二)

程序员文章站 2022-05-16 09:31:42
...

在国际化软件的时间日期格式方面,我们耳熟能详的有Moment,GlobalizeJS等,那么Singleton又是如何解决该问题呢?

宏观上看,Singleton并没有使用嵌入源码的lib模式,而是提供了两个service(目前共发布了两个版本的API,v1做出初始版本已基本被弃用,v2经过与多个产品磨合后,成为了包含类型最多并且较接近Restful API风格的一版,本文所有效果都基于后者)。

Singleton的格式API,已经覆盖的国际化关注点包括了日期时间、数字、货币、计量单位、单复数,主要API包括以下两个。

 

第一个API通过语言+地区返回请求类型的模式数据。

GET /i18n/api/v2/formatting/patterns

请求参数包括:

language: (必填)string类型,请求模式的语言,例如en、en-CA、zh-Hans等(已对zh-CN进行了扩展,效果等同于zh-Hans)

region: (必填)string类型,请求模式的区域;例如US、CN等

scope: (必填)string类型,请求模式的类型,选项为“dates,numbers,currencies,plurals,measurements” 其中的一个或多个。若需要同时请求多个,需要以半角逗号(,)分隔。

返回值:(JSON对象)返回对应请求类型的模式数据。

以简体中文为例,做下列请求。

https://XXX/i18n/api/v2/formatting/patterns?language=zh-CN&region=CN&scope=dates

返回结果如下。

{
  "response": {
    "code": 200,
    "message": "OK",
    "serverTime": ""
  },
  "signature": "",
  "data": {
    "localeID": "zh-Hans",
    "language": "zh-CN",
    "region": "CN",
    "categories": {
      "dates": {
        "dayPeriodsFormat": {
          "narrow": [
            "上午",
            "下午"
          ],
          "abbreviated": [
            "上午",
            "下午"
          ],
          "wide": [
            "上午",
            "下午"
          ]
        },
        "dayPeriodsStandalone": {
          "narrow": [
            "上午",
            "下午"
          ],
          "abbreviated": [
            "上午",
            "下午"
          ],
          "wide": [
            "上午",
            "下午"
          ]
        },
        "daysFormat": {
          "narrow": [
            "日",
            "一",
            "二",
            "三",
            "四",
            "五",
            "六"
          ],
          "abbreviated": [
            "周日",
            "周一",
            "周二",
            "周三",
            "周四",
            "周五",
            "周六"
          ],
          "wide": [
            "星期日",
            "星期一",
            "星期二",
            "星期三",
            "星期四",
            "星期五",
            "星期六"
          ],
          "short": [
            "周日",
            "周一",
            "周二",
            "周三",
            "周四",
            "周五",
            "周六"
          ]
        },
        "daysStandalone": {
          "narrow": [
            "日",
            "一",
            "二",
            "三",
            "四",
            "五",
            "六"
          ],
          "abbreviated": [
            "周日",
            "周一",
            "周二",
            "周三",
            "周四",
            "周五",
            "周六"
          ],
          "wide": [
            "星期日",
            "星期一",
            "星期二",
            "星期三",
            "星期四",
            "星期五",
            "星期六"
          ],
          "short": [
            "周日",
            "周一",
            "周二",
            "周三",
            "周四",
            "周五",
            "周六"
          ]
        },
        "monthsFormat": {
          "narrow": [
            "1",
            "2",
            "3",
            "4",
            "5",
            "6",
            "7",
            "8",
            "9",
            "10",
            "11",
            "12"
          ],
          "abbreviated": [
            "1月",
            "2月",
            "3月",
            "4月",
            "5月",
            "6月",
            "7月",
            "8月",
            "9月",
            "10月",
            "11月",
            "12月"
          ],
          "wide": [
            "一月",
            "二月",
            "三月",
            "四月",
            "五月",
            "六月",
            "七月",
            "八月",
            "九月",
            "十月",
            "十一月",
            "十二月"
          ]
        },
        "monthsStandalone": {
          "narrow": [
            "1",
            "2",
            "3",
            "4",
            "5",
            "6",
            "7",
            "8",
            "9",
            "10",
            "11",
            "12"
          ],
          "abbreviated": [
            "1月",
            "2月",
            "3月",
            "4月",
            "5月",
            "6月",
            "7月",
            "8月",
            "9月",
            "10月",
            "11月",
            "12月"
          ],
          "wide": [
            "一月",
            "二月",
            "三月",
            "四月",
            "五月",
            "六月",
            "七月",
            "八月",
            "九月",
            "十月",
            "十一月",
            "十二月"
          ]
        },
        "eras": {
          "narrow": [
            "公元前",
            "公元"
          ],
          "abbreviated": [
            "公元前",
            "公元"
          ],
          "wide": [
            "公元前",
            "公元"
          ]
        },
        "firstDayOfWeek": 0,
        "weekendRange": [
          6,
          0
        ],
        "dateFormats": {
          "short": "y/M/d",
          "medium": "y年M月d日",
          "long": "y年M月d日",
          "full": "y年M月d日EEEE"
        },
        "timeFormats": {
          "short": "ah:mm",
          "medium": "ah:mm:ss",
          "long": "z ah:mm:ss",
          "full": "zzzz ah:mm:ss"
        },
        "dateTimeFormats": {
          "short": "{1} {0}",
          "medium": "{1} {0}",
          "long": "{1} {0}",
          "full": "{1} {0}",
          "availableFormats": {
            "Bh": "Bh时",
            "Bhm": "Bh:mm",
            "Bhms": "Bh:mm:ss",
            "d": "d日",
            "E": "ccc",
            "EBhm": "EBh:mm",
            "EBhms": "EBh:mm:ss",
            "Ed": "d日E",
            "Ehm": "Eah:mm",
            "EHm": "EHH:mm",
            "Ehms": "Eah:mm:ss",
            "EHms": "EHH:mm:ss",
            "Gy": "Gy年",
            "GyMMM": "Gy年M月",
            "GyMMMd": "Gy年M月d日",
            "GyMMMEd": "Gy年M月d日E",
            "H": "H时",
            "h": "ah时",
            "hm": "ah:mm",
            "Hm": "HH:mm",
            "hms": "ah:mm:ss",
            "Hms": "HH:mm:ss",
            "hmsv": "v ah:mm:ss",
            "Hmsv": "v HH:mm:ss",
            "hmv": "v ah:mm",
            "Hmv": "v HH:mm",
            "M": "M月",
            "Md": "M/d",
            "MEd": "M/dE",
            "MMdd": "MM/dd",
            "MMM": "LLL",
            "MMMd": "M月d日",
            "MMMEd": "M月d日E",
            "MMMMd": "M月d日",
            "MMMMW-count-other": "MMM第W周",
            "ms": "mm:ss",
            "y": "y年",
            "yM": "y年M月",
            "yMd": "y/M/d",
            "yMEd": "y/M/dE",
            "yMM": "y年M月",
            "yMMM": "y年M月",
            "yMMMd": "y年M月d日",
            "yMMMEd": "y年M月d日E",
            "yMMMM": "y年M月",
            "yQQQ": "y年第Q季度",
            "yQQQQ": "y年第Q季度",
            "yw-count-other": "Y年第w周"
          },
          "appendItems": {
            "Day": "{0} ({2}: {1})",
            "Day-Of-Week": "{0} {1}",
            "Era": "{1} {0}",
            "Hour": "{0} ({2}: {1})",
            "Minute": "{0} ({2}: {1})",
            "Month": "{0} ({2}: {1})",
            "Quarter": "{0} ({2}: {1})",
            "Second": "{0} ({2}: {1})",
            "Timezone": "{1}{0}",
            "Week": "{0} ({2}: {1})",
            "Year": "{1} {0}"
          },
          "intervalFormats": {
            "d": {
              "d": "d–d日"
            },
            "h": {
              "a": "ah时至ah时",
              "h": "ah时至h时"
            },
            "H": {
              "H": "HH–HH"
            },
            "hm": {
              "a": "ah:mm至ah:mm",
              "h": "ah:mm至h:mm",
              "m": "ah:mm至h:mm"
            },
            "Hm": {
              "H": "HH:mm–HH:mm",
              "m": "HH:mm–HH:mm"
            },
            "hmv": {
              "a": "vah:mm至ah:mm",
              "h": "vah:mm至h:mm",
              "m": "vah:mm至h:mm"
            },
            "Hmv": {
              "H": "v HH:mm–HH:mm",
              "m": "v HH:mm–HH:mm"
            },
            "hv": {
              "a": "vah时至ah时",
              "h": "vah时至h时"
            },
            "Hv": {
              "H": "v HH–HH"
            },
            "intervalFormatFallback": "{0} – {1}",
            "M": {
              "M": "M–M月"
            },
            "Md": {
              "d": "M/d – M/d",
              "M": "M/d – M/d"
            },
            "MEd": {
              "d": "M/dE至M/dE",
              "M": "M/dE至M/dE"
            },
            "MMM": {
              "M": "MMM – MMM"
            },
            "MMMd": {
              "d": "M月d日至d日",
              "M": "M月d日至M月d日"
            },
            "MMMEd": {
              "d": "M月d日E至d日E",
              "M": "M月d日E至M月d日E"
            },
            "y": {
              "y": "y–y年"
            },
            "yM": {
              "y": "y年M月至y年M月",
              "M": "y年M月至M月"
            },
            "yMd": {
              "d": "y/M/d – y/M/d",
              "y": "y/M/d – y/M/d",
              "M": "y/M/d – y/M/d"
            },
            "yMEd": {
              "d": "y/M/dE至y/M/dE",
              "y": "y/M/dE至y/M/dE",
              "M": "y/M/dE至y/M/dE"
            },
            "yMMM": {
              "y": "y年M月至y年M月",
              "M": "y年M月至M月"
            },
            "yMMMd": {
              "d": "y年M月d日至d日",
              "y": "y年M月d日至y年M月d日",
              "M": "y年M月d日至M月d日"
            },
            "yMMMEd": {
              "d": "y年M月d日E至d日E",
              "y": "y年M月d日E至y年M月d日E",
              "M": "y年M月d日E至M月d日E"
            },
            "yMMMM": {
              "y": "y年M月至y年M月",
              "M": "y年M月至M月"
            }
          }
        }
      },
      "supplemental": {
        "dates": null
      }
    }
  }
}

在调用过程中需要注意以下几点:

  1. 请求的语言+地区如果是一个有效的组合(例如en-US、zh-Hans),返回的模式类型为此有效组合对应的数据
  2. 一旦请求的语言+地区无效(例如en-JP),此时返回的模式数据以地区为主,返回请求地区中最多人口使用的语言的模式数据(scope中的“plurals”除外)
  3. scope中的“plurals”,无论请求的语言和地区进行怎样的组合,始终以语言为判断依据

 

另一个则是通过提供预先组合好的区域设置,返回请求类型的模式数据。

GET /i18n/api/v2/formatting/patterns/locales/{locale}

请求参数:

locale: (必填)string类型,请求模式数据的区域,例如en,en-GB,zh-Hans,zh-Hans-CN等

scope: (必填)string类型,请求模式的类型,需要从“dates,numbers,currencies,plurals,measurements”中做出选择。若同时请求多个,以半角逗号(,)进行分隔。

这里我进行了zh-CN的货币请求,部分结果如下:

{
  "response": {
    "code": 200,
    "message": "OK",
    "serverTime": ""
  },
  "signature": "",
  "data": {
    "localeID": "zh-Hans",
    "language": "zh",
    "region": "CN",
    "categories": {
      "currencies": {
        "AED": {
          "symbol": "AED",
          "displayName": "阿联酋迪拉姆",
          "displayName-count-other": "阿联酋迪拉姆"
        },
        
        "CAD": {
          "symbol": "CA$",
          "displayName": "加拿大元",
          "symbol-alt-narrow": "$",
          "displayName-count-other": "加拿大元"
        },
        "CHE": {
          "symbol": "CHE",
          "displayName": "欧元 (WIR)",
          "displayName-count-other": "欧元 (WIR)"
        },
        "CHF": {
          "symbol": "CHF",
          "displayName": "瑞士法郎",
          "displayName-count-other": "瑞士法郎"
        },
        "CHW": {
          "symbol": "CHW",
          "displayName": "法郎 (WIR)",
          "displayName-count-other": "法郎 (WIR)"
        },
        "CLE": {
          "symbol": "CLE",
          "displayName": "智利埃斯库多",
          "displayName-count-other": "智利埃斯库多"
        },
        "CLF": {
          "symbol": "CLF",
          "displayName": "智利(资金)",
          "displayName-count-other": "智利(资金)"
        },
        "CLP": {
          "symbol": "CLP",
          "displayName": "智利比索",
          "symbol-alt-narrow": "$",
          "displayName-count-other": "智利比索"
        },
        "CNH": {
          "symbol": "CNH",
          "displayName": "人民币(离岸)",
          "displayName-count-other": "人民币(离岸)"
        },
        "CNX": {
          "symbol": "CNX",
          "displayName": "CNX"
        },
        "CNY": {
          "symbol": "¥",
          "displayName": "人民币",
          "symbol-alt-narrow": "¥",
          "displayName-count-other": "人民币"
        },
        "DEM": {
          "symbol": "DEM",
          "displayName": "德国马克",
          "displayName-count-other": "德国马克"
        },
        "HKD": {
          "symbol": "HK$",
          "displayName": "港元",
          "symbol-alt-narrow": "$",
          "displayName-count-other": "港元"
        },
        "JPY": {
          "symbol": "JP¥",
          "displayName": "日元",
          "symbol-alt-narrow": "¥",
          "displayName-count-other": "日元"
        },
        "KPW": {
          "symbol": "KPW",
          "displayName": "朝鲜元",
          "symbol-alt-narrow": "₩",
          "displayName-count-other": "朝鲜元"
        },
        "KRH": {
          "symbol": "KRH",
          "displayName": "韩元 (1953–1962)"
        },
        "KRO": {
          "symbol": "KRO",
          "displayName": "韩元 (1945–1953)"
        },
        "KRW": {
          "symbol": "₩",
          "displayName": "韩元",
          "symbol-alt-narrow": "₩",
          "displayName-count-other": "韩元"
        },
          },
          "region": {
	…
            "NL": "EUR",
            "NO": "NOK",
            "NP": "NPR",
            "NR": "AUD",
            "NU": "NZD",
            "NZ": "NZD",
            "OM": "OMR",
            "PA": "USD",
            "PE": "PEN",
            "PF": "XPF",
            "PG": "PGK",
            "PH": "PHP",
            "PK": "PKR",
            "PL": "PLN",
            "PM": "EUR",
            "PN": "NZD"
          }
        }
      }
    }
  }
}

而使用Moment处理同样问题的效果,我在18年的博文中已经进行了详述。对比之后不难发现,Moment作为较为大众的国际化时间日期库,优势在于其深度,不仅在时间日期方面有着优秀的表现,同时困扰国际化软件开发从业人员的calendar问题,也被囊括其中。而Singleton在面对该特定问题时,优势则在于其提供的微服务方式以及广度(灵活度),但各个国家地区的日历问题依然没有被解决,不得不说这是一个很大的遗憾。

相关标签: i18n