Jelajahi Sumber

add FmtPercent logic.

joeybloggs 9 tahun lalu
induk
melakukan
fb2acb9360
100 mengubah file dengan 3591 tambahan dan 12 penghapusan
  1. 35 0
      af/af.go
  2. 35 0
      af_NA/af_NA.go
  3. 35 0
      af_ZA/af_ZA.go
  4. 39 0
      agq/agq.go
  5. 39 0
      agq_CM/agq_CM.go
  6. 10 0
      ak/ak.go
  7. 10 0
      ak_GH/ak_GH.go
  8. 35 0
      am/am.go
  9. 35 0
      am_ET/am_ET.go
  10. 42 0
      ar/ar.go
  11. 42 0
      ar_001/ar_001.go
  12. 42 0
      ar_AE/ar_AE.go
  13. 42 0
      ar_BH/ar_BH.go
  14. 42 0
      ar_DJ/ar_DJ.go
  15. 39 0
      ar_DZ/ar_DZ.go
  16. 42 0
      ar_EG/ar_EG.go
  17. 42 0
      ar_EH/ar_EH.go
  18. 42 0
      ar_ER/ar_ER.go
  19. 42 0
      ar_IL/ar_IL.go
  20. 42 0
      ar_IQ/ar_IQ.go
  21. 42 0
      ar_JO/ar_JO.go
  22. 42 0
      ar_KM/ar_KM.go
  23. 42 0
      ar_KW/ar_KW.go
  24. 39 0
      ar_LB/ar_LB.go
  25. 39 0
      ar_LY/ar_LY.go
  26. 39 0
      ar_MA/ar_MA.go
  27. 39 0
      ar_MR/ar_MR.go
  28. 42 0
      ar_OM/ar_OM.go
  29. 42 0
      ar_PS/ar_PS.go
  30. 42 0
      ar_QA/ar_QA.go
  31. 42 0
      ar_SA/ar_SA.go
  32. 42 0
      ar_SD/ar_SD.go
  33. 42 0
      ar_SO/ar_SO.go
  34. 42 0
      ar_SS/ar_SS.go
  35. 42 0
      ar_SY/ar_SY.go
  36. 42 0
      ar_TD/ar_TD.go
  37. 39 0
      ar_TN/ar_TN.go
  38. 42 0
      ar_YE/ar_YE.go
  39. 42 0
      as/as.go
  40. 42 0
      as_IN/as_IN.go
  41. 10 0
      asa/asa.go
  42. 10 0
      asa_TZ/asa_TZ.go
  43. 42 0
      ast/ast.go
  44. 42 0
      ast_ES/ast_ES.go
  45. 36 1
      az/az.go
  46. 35 0
      az_Cyrl/az_Cyrl.go
  47. 36 1
      az_Cyrl_AZ/az_Cyrl_AZ.go
  48. 35 0
      az_Latn/az_Latn.go
  49. 35 0
      az_Latn_AZ/az_Latn_AZ.go
  50. 39 0
      bas/bas.go
  51. 39 0
      bas_CM/bas_CM.go
  52. 37 2
      be/be.go
  53. 36 1
      be_BY/be_BY.go
  54. 10 0
      bem/bem.go
  55. 10 0
      bem_ZM/bem_ZM.go
  56. 10 0
      bez/bez.go
  57. 10 0
      bez_TZ/bez_TZ.go
  58. 35 0
      bg/bg.go
  59. 35 0
      bg_BG/bg_BG.go
  60. 10 0
      bm/bm.go
  61. 10 0
      bm_ML/bm_ML.go
  62. 42 0
      bn/bn.go
  63. 42 0
      bn_BD/bn_BD.go
  64. 42 0
      bn_IN/bn_IN.go
  65. 39 0
      bo/bo.go
  66. 39 0
      bo_CN/bo_CN.go
  67. 39 0
      bo_IN/bo_IN.go
  68. 42 0
      br/br.go
  69. 42 0
      br_FR/br_FR.go
  70. 35 0
      brx/brx.go
  71. 35 0
      brx_IN/brx_IN.go
  72. 36 1
      bs/bs.go
  73. 37 2
      bs_Cyrl/bs_Cyrl.go
  74. 35 0
      bs_Cyrl_BA/bs_Cyrl_BA.go
  75. 35 0
      bs_Latn/bs_Latn.go
  76. 35 0
      bs_Latn_BA/bs_Latn_BA.go
  77. 35 0
      ca/ca.go
  78. 35 0
      ca_AD/ca_AD.go
  79. 35 0
      ca_ES/ca_ES.go
  80. 35 0
      ca_ES_VALENCIA/ca_ES_VALENCIA.go
  81. 35 0
      ca_FR/ca_FR.go
  82. 35 0
      ca_IT/ca_IT.go
  83. 35 0
      ce/ce.go
  84. 35 0
      ce_RU/ce_RU.go
  85. 10 0
      cgg/cgg.go
  86. 10 0
      cgg_UG/cgg_UG.go
  87. 35 0
      chr/chr.go
  88. 35 0
      chr_US/chr_US.go
  89. 10 0
      ckb/ckb.go
  90. 10 0
      ckb_IQ/ckb_IQ.go
  91. 10 0
      ckb_IR/ckb_IR.go
  92. 92 4
      cmd/generate_resources.go
  93. 132 0
      cmd/translator.tmpl
  94. 42 0
      cs/cs.go
  95. 42 0
      cs_CZ/cs_CZ.go
  96. 35 0
      cu/cu.go
  97. 35 0
      cu_RU/cu_RU.go
  98. 42 0
      cy/cy.go
  99. 42 0
      cy_GB/cy_GB.go
  100. 35 0
      da/da.go

+ 35 - 0
af/af.go

@@ -117,3 +117,38 @@ func (af *af) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'af' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (af *af) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(af.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, af.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, af.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, af.Percent[0])
+
+	return b
+}

+ 35 - 0
af_NA/af_NA.go

@@ -117,3 +117,38 @@ func (af *af_NA) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'af_NA' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (af *af_NA) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(af.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, af.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, af.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, af.Percent[0])
+
+	return b
+}

+ 35 - 0
af_ZA/af_ZA.go

@@ -117,3 +117,38 @@ func (af *af_ZA) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'af_ZA' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (af *af_ZA) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(af.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, af.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, af.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, af.Percent[0])
+
+	return b
+}

+ 39 - 0
agq/agq.go

@@ -112,3 +112,42 @@ func (agq *agq) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'agq' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (agq *agq) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(agq.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, agq.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(agq.minus) - 1; j >= 0; j-- {
+			b = append(b, agq.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(agq.percent) - 1; j >= 0; j-- {
+		b = append(b, agq.percent[j])
+	}
+
+	return b
+}

+ 39 - 0
agq_CM/agq_CM.go

@@ -112,3 +112,42 @@ func (agq *agq_CM) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'agq_CM' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (agq *agq_CM) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(agq.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, agq.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(agq.minus) - 1; j >= 0; j-- {
+			b = append(b, agq.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(agq.percent) - 1; j >= 0; j-- {
+		b = append(b, agq.percent[j])
+	}
+
+	return b
+}

+ 10 - 0
ak/ak.go

@@ -79,3 +79,13 @@ func (ak *ak) FmtNumber(num float64, v uint64) []byte {
 	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
 	return []byte(s)
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ak' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ak *ak) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	return []byte(s)
+}

+ 10 - 0
ak_GH/ak_GH.go

@@ -79,3 +79,13 @@ func (ak *ak_GH) FmtNumber(num float64, v uint64) []byte {
 	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
 	return []byte(s)
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ak_GH' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ak *ak_GH) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	return []byte(s)
+}

+ 35 - 0
am/am.go

@@ -126,3 +126,38 @@ func (am *am) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'am' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (am *am) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(am.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, am.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, am.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, am.Percent[0])
+
+	return b
+}

+ 35 - 0
am_ET/am_ET.go

@@ -126,3 +126,38 @@ func (am *am_ET) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'am_ET' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (am *am_ET) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(am.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, am.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, am.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, am.Percent[0])
+
+	return b
+}

+ 42 - 0
ar/ar.go

@@ -182,3 +182,45 @@ func (ar *ar) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_001/ar_001.go

@@ -182,3 +182,45 @@ func (ar *ar_001) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_001' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_001) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_AE/ar_AE.go

@@ -182,3 +182,45 @@ func (ar *ar_AE) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_AE' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_AE) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_BH/ar_BH.go

@@ -182,3 +182,45 @@ func (ar *ar_BH) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_BH' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_BH) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_DJ/ar_DJ.go

@@ -182,3 +182,45 @@ func (ar *ar_DJ) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_DJ' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_DJ) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 39 - 0
ar_DZ/ar_DZ.go

@@ -176,3 +176,42 @@ func (ar *ar_DZ) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_DZ' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_DZ) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, ar.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_EG/ar_EG.go

@@ -182,3 +182,45 @@ func (ar *ar_EG) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_EG' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_EG) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_EH/ar_EH.go

@@ -182,3 +182,45 @@ func (ar *ar_EH) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_EH' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_EH) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_ER/ar_ER.go

@@ -182,3 +182,45 @@ func (ar *ar_ER) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_ER' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_ER) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_IL/ar_IL.go

@@ -182,3 +182,45 @@ func (ar *ar_IL) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_IL' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_IL) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_IQ/ar_IQ.go

@@ -182,3 +182,45 @@ func (ar *ar_IQ) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_IQ' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_IQ) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_JO/ar_JO.go

@@ -182,3 +182,45 @@ func (ar *ar_JO) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_JO' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_JO) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_KM/ar_KM.go

@@ -182,3 +182,45 @@ func (ar *ar_KM) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_KM' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_KM) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_KW/ar_KW.go

@@ -182,3 +182,45 @@ func (ar *ar_KW) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_KW' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_KW) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 39 - 0
ar_LB/ar_LB.go

@@ -176,3 +176,42 @@ func (ar *ar_LB) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_LB' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_LB) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, ar.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 39 - 0
ar_LY/ar_LY.go

@@ -176,3 +176,42 @@ func (ar *ar_LY) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_LY' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_LY) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, ar.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 39 - 0
ar_MA/ar_MA.go

@@ -176,3 +176,42 @@ func (ar *ar_MA) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_MA' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_MA) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, ar.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 39 - 0
ar_MR/ar_MR.go

@@ -176,3 +176,42 @@ func (ar *ar_MR) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_MR' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_MR) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, ar.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_OM/ar_OM.go

@@ -182,3 +182,45 @@ func (ar *ar_OM) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_OM' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_OM) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_PS/ar_PS.go

@@ -182,3 +182,45 @@ func (ar *ar_PS) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_PS' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_PS) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_QA/ar_QA.go

@@ -182,3 +182,45 @@ func (ar *ar_QA) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_QA' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_QA) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_SA/ar_SA.go

@@ -182,3 +182,45 @@ func (ar *ar_SA) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_SA' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_SA) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_SD/ar_SD.go

@@ -182,3 +182,45 @@ func (ar *ar_SD) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_SD' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_SD) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_SO/ar_SO.go

@@ -182,3 +182,45 @@ func (ar *ar_SO) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_SO' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_SO) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_SS/ar_SS.go

@@ -182,3 +182,45 @@ func (ar *ar_SS) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_SS' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_SS) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_SY/ar_SY.go

@@ -182,3 +182,45 @@ func (ar *ar_SY) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_SY' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_SY) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_TD/ar_TD.go

@@ -182,3 +182,45 @@ func (ar *ar_TD) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_TD' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_TD) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 39 - 0
ar_TN/ar_TN.go

@@ -176,3 +176,42 @@ func (ar *ar_TN) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_TN' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_TN) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, ar.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ar_YE/ar_YE.go

@@ -182,3 +182,45 @@ func (ar *ar_YE) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ar_YE' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ar *ar_YE) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ar.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ar.decimal) - 1; j >= 0; j-- {
+				b = append(b, ar.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ar.minus) - 1; j >= 0; j-- {
+			b = append(b, ar.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ar.percent) - 1; j >= 0; j-- {
+		b = append(b, ar.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
as/as.go

@@ -145,3 +145,45 @@ func (as *as) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'as' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (as *as) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(as.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(as.decimal) - 1; j >= 0; j-- {
+				b = append(b, as.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(as.minus) - 1; j >= 0; j-- {
+			b = append(b, as.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(as.percent) - 1; j >= 0; j-- {
+		b = append(b, as.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
as_IN/as_IN.go

@@ -145,3 +145,45 @@ func (as *as_IN) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'as_IN' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (as *as_IN) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(as.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(as.decimal) - 1; j >= 0; j-- {
+				b = append(b, as.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(as.minus) - 1; j >= 0; j-- {
+			b = append(b, as.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(as.percent) - 1; j >= 0; j-- {
+		b = append(b, as.percent[j])
+	}
+
+	return b
+}

+ 10 - 0
asa/asa.go

@@ -79,3 +79,13 @@ func (asa *asa) FmtNumber(num float64, v uint64) []byte {
 	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
 	return []byte(s)
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'asa' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (asa *asa) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	return []byte(s)
+}

+ 10 - 0
asa_TZ/asa_TZ.go

@@ -79,3 +79,13 @@ func (asa *asa_TZ) FmtNumber(num float64, v uint64) []byte {
 	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
 	return []byte(s)
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'asa_TZ' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (asa *asa_TZ) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	return []byte(s)
+}

+ 42 - 0
ast/ast.go

@@ -123,3 +123,45 @@ func (ast *ast) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ast' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ast *ast) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ast.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ast.decimal) - 1; j >= 0; j-- {
+				b = append(b, ast.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ast.minus) - 1; j >= 0; j-- {
+			b = append(b, ast.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ast.percent) - 1; j >= 0; j-- {
+		b = append(b, ast.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
ast_ES/ast_ES.go

@@ -123,3 +123,45 @@ func (ast *ast_ES) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ast_ES' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ast *ast_ES) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ast.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(ast.decimal) - 1; j >= 0; j-- {
+				b = append(b, ast.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(ast.minus) - 1; j >= 0; j-- {
+			b = append(b, ast.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(ast.percent) - 1; j >= 0; j-- {
+		b = append(b, ast.percent[j])
+	}
+
+	return b
+}

+ 36 - 1
az/az.go

@@ -66,9 +66,9 @@ func (az *az) OrdinalPluralRule(num float64, v uint64) locales.PluralRule {
 
 	n := math.Abs(num)
 	i := int64(n)
-	iMod1000 := i % 1000
 	iMod10 := i % 10
 	iMod100 := i % 100
+	iMod1000 := i % 1000
 
 	if (iMod10 == 1 || iMod10 == 2 || iMod10 == 5 || iMod10 == 7 || iMod10 == 8) || (iMod100 == 20 || iMod100 == 50 || iMod100 == 70 || iMod100 == 80) {
 		return locales.PluralRuleOne
@@ -140,3 +140,38 @@ func (az *az) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'az' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (az *az) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(az.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, az.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, az.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, az.Percent[0])
+
+	return b
+}

+ 35 - 0
az_Cyrl/az_Cyrl.go

@@ -140,3 +140,38 @@ func (az *az_Cyrl) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'az_Cyrl' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (az *az_Cyrl) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(az.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, az.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, az.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, az.Percent[0])
+
+	return b
+}

+ 36 - 1
az_Cyrl_AZ/az_Cyrl_AZ.go

@@ -66,9 +66,9 @@ func (az *az_Cyrl_AZ) OrdinalPluralRule(num float64, v uint64) locales.PluralRul
 
 	n := math.Abs(num)
 	i := int64(n)
-	iMod1000 := i % 1000
 	iMod10 := i % 10
 	iMod100 := i % 100
+	iMod1000 := i % 1000
 
 	if (iMod10 == 1 || iMod10 == 2 || iMod10 == 5 || iMod10 == 7 || iMod10 == 8) || (iMod100 == 20 || iMod100 == 50 || iMod100 == 70 || iMod100 == 80) {
 		return locales.PluralRuleOne
@@ -140,3 +140,38 @@ func (az *az_Cyrl_AZ) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'az_Cyrl_AZ' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (az *az_Cyrl_AZ) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(az.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, az.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, az.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, az.Percent[0])
+
+	return b
+}

+ 35 - 0
az_Latn/az_Latn.go

@@ -140,3 +140,38 @@ func (az *az_Latn) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'az_Latn' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (az *az_Latn) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(az.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, az.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, az.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, az.Percent[0])
+
+	return b
+}

+ 35 - 0
az_Latn_AZ/az_Latn_AZ.go

@@ -140,3 +140,38 @@ func (az *az_Latn_AZ) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'az_Latn_AZ' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (az *az_Latn_AZ) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(az.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, az.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, az.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, az.Percent[0])
+
+	return b
+}

+ 39 - 0
bas/bas.go

@@ -112,3 +112,42 @@ func (bas *bas) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bas' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bas *bas) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(bas.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, bas.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(bas.minus) - 1; j >= 0; j-- {
+			b = append(b, bas.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(bas.percent) - 1; j >= 0; j-- {
+		b = append(b, bas.percent[j])
+	}
+
+	return b
+}

+ 39 - 0
bas_CM/bas_CM.go

@@ -112,3 +112,42 @@ func (bas *bas_CM) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bas_CM' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bas *bas_CM) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(bas.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, bas.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(bas.minus) - 1; j >= 0; j-- {
+			b = append(b, bas.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(bas.percent) - 1; j >= 0; j-- {
+		b = append(b, bas.percent[j])
+	}
+
+	return b
+}

+ 37 - 2
be/be.go

@@ -53,8 +53,8 @@ func (be *be) PluralsOrdinal() []locales.PluralRule {
 func (be *be) CardinalPluralRule(num float64, v uint64) locales.PluralRule {
 
 	n := math.Abs(num)
-	nMod10 := math.Mod(n, 10)
 	nMod100 := math.Mod(n, 100)
+	nMod10 := math.Mod(n, 10)
 
 	if nMod10 == 1 && nMod100 != 11 {
 		return locales.PluralRuleOne
@@ -71,8 +71,8 @@ func (be *be) CardinalPluralRule(num float64, v uint64) locales.PluralRule {
 func (be *be) OrdinalPluralRule(num float64, v uint64) locales.PluralRule {
 
 	n := math.Abs(num)
-	nMod10 := math.Mod(n, 10)
 	nMod100 := math.Mod(n, 100)
+	nMod10 := math.Mod(n, 10)
 
 	if (nMod10 == 2 || nMod10 == 3) && (nMod100 != 12 && nMod100 != 13) {
 		return locales.PluralRuleFew
@@ -132,3 +132,38 @@ func (be *be) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'be' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (be *be) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(be.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, be.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, be.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, be.Percent[0])
+
+	return b
+}

+ 36 - 1
be_BY/be_BY.go

@@ -71,8 +71,8 @@ func (be *be_BY) CardinalPluralRule(num float64, v uint64) locales.PluralRule {
 func (be *be_BY) OrdinalPluralRule(num float64, v uint64) locales.PluralRule {
 
 	n := math.Abs(num)
-	nMod10 := math.Mod(n, 10)
 	nMod100 := math.Mod(n, 100)
+	nMod10 := math.Mod(n, 10)
 
 	if (nMod10 == 2 || nMod10 == 3) && (nMod100 != 12 && nMod100 != 13) {
 		return locales.PluralRuleFew
@@ -132,3 +132,38 @@ func (be *be_BY) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'be_BY' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (be *be_BY) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(be.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, be.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, be.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, be.Percent[0])
+
+	return b
+}

+ 10 - 0
bem/bem.go

@@ -79,3 +79,13 @@ func (bem *bem) FmtNumber(num float64, v uint64) []byte {
 	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
 	return []byte(s)
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bem' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bem *bem) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	return []byte(s)
+}

+ 10 - 0
bem_ZM/bem_ZM.go

@@ -79,3 +79,13 @@ func (bem *bem_ZM) FmtNumber(num float64, v uint64) []byte {
 	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
 	return []byte(s)
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bem_ZM' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bem *bem_ZM) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	return []byte(s)
+}

+ 10 - 0
bez/bez.go

@@ -79,3 +79,13 @@ func (bez *bez) FmtNumber(num float64, v uint64) []byte {
 	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
 	return []byte(s)
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bez' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bez *bez) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	return []byte(s)
+}

+ 10 - 0
bez_TZ/bez_TZ.go

@@ -79,3 +79,13 @@ func (bez *bez_TZ) FmtNumber(num float64, v uint64) []byte {
 	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
 	return []byte(s)
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bez_TZ' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bez *bez_TZ) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	return []byte(s)
+}

+ 35 - 0
bg/bg.go

@@ -117,3 +117,38 @@ func (bg *bg) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bg' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bg *bg) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(bg.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, bg.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, bg.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, bg.Percent[0])
+
+	return b
+}

+ 35 - 0
bg_BG/bg_BG.go

@@ -117,3 +117,38 @@ func (bg *bg_BG) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bg_BG' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bg *bg_BG) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(bg.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, bg.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, bg.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, bg.Percent[0])
+
+	return b
+}

+ 10 - 0
bm/bm.go

@@ -72,3 +72,13 @@ func (bm *bm) FmtNumber(num float64, v uint64) []byte {
 	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
 	return []byte(s)
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bm' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bm *bm) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	return []byte(s)
+}

+ 10 - 0
bm_ML/bm_ML.go

@@ -72,3 +72,13 @@ func (bm *bm_ML) FmtNumber(num float64, v uint64) []byte {
 	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
 	return []byte(s)
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bm_ML' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bm *bm_ML) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	return []byte(s)
+}

+ 42 - 0
bn/bn.go

@@ -156,3 +156,45 @@ func (bn *bn) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bn' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bn *bn) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(bn.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(bn.decimal) - 1; j >= 0; j-- {
+				b = append(b, bn.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(bn.minus) - 1; j >= 0; j-- {
+			b = append(b, bn.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(bn.percent) - 1; j >= 0; j-- {
+		b = append(b, bn.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
bn_BD/bn_BD.go

@@ -156,3 +156,45 @@ func (bn *bn_BD) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bn_BD' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bn *bn_BD) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(bn.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(bn.decimal) - 1; j >= 0; j-- {
+				b = append(b, bn.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(bn.minus) - 1; j >= 0; j-- {
+			b = append(b, bn.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(bn.percent) - 1; j >= 0; j-- {
+		b = append(b, bn.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
bn_IN/bn_IN.go

@@ -156,3 +156,45 @@ func (bn *bn_IN) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bn_IN' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bn *bn_IN) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(bn.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(bn.decimal) - 1; j >= 0; j-- {
+				b = append(b, bn.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(bn.minus) - 1; j >= 0; j-- {
+			b = append(b, bn.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(bn.percent) - 1; j >= 0; j-- {
+		b = append(b, bn.percent[j])
+	}
+
+	return b
+}

+ 39 - 0
bo/bo.go

@@ -109,3 +109,42 @@ func (bo *bo) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bo' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bo *bo) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(bo.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, bo.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(bo.minus) - 1; j >= 0; j-- {
+			b = append(b, bo.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(bo.percent) - 1; j >= 0; j-- {
+		b = append(b, bo.percent[j])
+	}
+
+	return b
+}

+ 39 - 0
bo_CN/bo_CN.go

@@ -109,3 +109,42 @@ func (bo *bo_CN) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bo_CN' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bo *bo_CN) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(bo.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, bo.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(bo.minus) - 1; j >= 0; j-- {
+			b = append(b, bo.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(bo.percent) - 1; j >= 0; j-- {
+		b = append(b, bo.percent[j])
+	}
+
+	return b
+}

+ 39 - 0
bo_IN/bo_IN.go

@@ -109,3 +109,42 @@ func (bo *bo_IN) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bo_IN' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bo *bo_IN) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(bo.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, bo.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(bo.minus) - 1; j >= 0; j-- {
+			b = append(b, bo.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(bo.percent) - 1; j >= 0; j-- {
+		b = append(b, bo.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
br/br.go

@@ -131,3 +131,45 @@ func (br *br) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'br' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (br *br) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(br.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(br.decimal) - 1; j >= 0; j-- {
+				b = append(b, br.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(br.minus) - 1; j >= 0; j-- {
+			b = append(b, br.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(br.percent) - 1; j >= 0; j-- {
+		b = append(b, br.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
br_FR/br_FR.go

@@ -131,3 +131,45 @@ func (br *br_FR) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'br_FR' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (br *br_FR) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(br.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(br.decimal) - 1; j >= 0; j-- {
+				b = append(b, br.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(br.minus) - 1; j >= 0; j-- {
+			b = append(b, br.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(br.percent) - 1; j >= 0; j-- {
+		b = append(b, br.percent[j])
+	}
+
+	return b
+}

+ 35 - 0
brx/brx.go

@@ -123,3 +123,38 @@ func (brx *brx) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'brx' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (brx *brx) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(brx.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, brx.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, brx.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, brx.Percent[0])
+
+	return b
+}

+ 35 - 0
brx_IN/brx_IN.go

@@ -123,3 +123,38 @@ func (brx *brx_IN) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'brx_IN' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (brx *brx_IN) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(brx.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, brx.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, brx.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, brx.Percent[0])
+
+	return b
+}

+ 36 - 1
bs/bs.go

@@ -55,8 +55,8 @@ func (bs *bs) CardinalPluralRule(num float64, v uint64) locales.PluralRule {
 	n := math.Abs(num)
 	i := int64(n)
 	f := locales.F(n, v)
-	iMod100 := i % 100
 	iMod10 := i % 10
+	iMod100 := i % 100
 	fMod10 := f % 10
 	fMod100 := f % 100
 
@@ -145,3 +145,38 @@ func (bs *bs) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bs' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bs *bs) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(bs.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, bs.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, bs.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, bs.Percent[0])
+
+	return b
+}

+ 37 - 2
bs_Cyrl/bs_Cyrl.go

@@ -55,10 +55,10 @@ func (bs *bs_Cyrl) CardinalPluralRule(num float64, v uint64) locales.PluralRule
 	n := math.Abs(num)
 	i := int64(n)
 	f := locales.F(n, v)
-	iMod10 := i % 10
 	iMod100 := i % 100
-	fMod100 := f % 100
+	iMod10 := i % 10
 	fMod10 := f % 10
+	fMod100 := f % 100
 
 	if (v == 0 && iMod10 == 1 && iMod100 != 11) || (fMod10 == 1 && fMod100 != 11) {
 		return locales.PluralRuleOne
@@ -145,3 +145,38 @@ func (bs *bs_Cyrl) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bs_Cyrl' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bs *bs_Cyrl) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(bs.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, bs.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, bs.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, bs.Percent[0])
+
+	return b
+}

+ 35 - 0
bs_Cyrl_BA/bs_Cyrl_BA.go

@@ -145,3 +145,38 @@ func (bs *bs_Cyrl_BA) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bs_Cyrl_BA' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bs *bs_Cyrl_BA) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(bs.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, bs.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, bs.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, bs.Percent[0])
+
+	return b
+}

+ 35 - 0
bs_Latn/bs_Latn.go

@@ -145,3 +145,38 @@ func (bs *bs_Latn) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bs_Latn' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bs *bs_Latn) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(bs.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, bs.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, bs.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, bs.Percent[0])
+
+	return b
+}

+ 35 - 0
bs_Latn_BA/bs_Latn_BA.go

@@ -145,3 +145,38 @@ func (bs *bs_Latn_BA) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'bs_Latn_BA' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (bs *bs_Latn_BA) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(bs.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, bs.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, bs.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, bs.Percent[0])
+
+	return b
+}

+ 35 - 0
ca/ca.go

@@ -126,3 +126,38 @@ func (ca *ca) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ca' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ca *ca) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ca.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, ca.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, ca.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, ca.Percent[0])
+
+	return b
+}

+ 35 - 0
ca_AD/ca_AD.go

@@ -126,3 +126,38 @@ func (ca *ca_AD) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ca_AD' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ca *ca_AD) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ca.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, ca.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, ca.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, ca.Percent[0])
+
+	return b
+}

+ 35 - 0
ca_ES/ca_ES.go

@@ -126,3 +126,38 @@ func (ca *ca_ES) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ca_ES' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ca *ca_ES) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ca.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, ca.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, ca.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, ca.Percent[0])
+
+	return b
+}

+ 35 - 0
ca_ES_VALENCIA/ca_ES_VALENCIA.go

@@ -126,3 +126,38 @@ func (ca *ca_ES_VALENCIA) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ca_ES_VALENCIA' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ca *ca_ES_VALENCIA) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ca.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, ca.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, ca.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, ca.Percent[0])
+
+	return b
+}

+ 35 - 0
ca_FR/ca_FR.go

@@ -126,3 +126,38 @@ func (ca *ca_FR) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ca_FR' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ca *ca_FR) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ca.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, ca.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, ca.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, ca.Percent[0])
+
+	return b
+}

+ 35 - 0
ca_IT/ca_IT.go

@@ -126,3 +126,38 @@ func (ca *ca_IT) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ca_IT' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ca *ca_IT) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ca.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, ca.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, ca.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, ca.Percent[0])
+
+	return b
+}

+ 35 - 0
ce/ce.go

@@ -114,3 +114,38 @@ func (ce *ce) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ce' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ce *ce) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ce.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, ce.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, ce.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, ce.Percent[0])
+
+	return b
+}

+ 35 - 0
ce_RU/ce_RU.go

@@ -114,3 +114,38 @@ func (ce *ce_RU) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ce_RU' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ce *ce_RU) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(ce.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, ce.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, ce.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, ce.Percent[0])
+
+	return b
+}

+ 10 - 0
cgg/cgg.go

@@ -79,3 +79,13 @@ func (cgg *cgg) FmtNumber(num float64, v uint64) []byte {
 	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
 	return []byte(s)
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'cgg' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (cgg *cgg) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	return []byte(s)
+}

+ 10 - 0
cgg_UG/cgg_UG.go

@@ -79,3 +79,13 @@ func (cgg *cgg_UG) FmtNumber(num float64, v uint64) []byte {
 	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
 	return []byte(s)
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'cgg_UG' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (cgg *cgg_UG) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	return []byte(s)
+}

+ 35 - 0
chr/chr.go

@@ -114,3 +114,38 @@ func (chr *chr) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'chr' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (chr *chr) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(chr.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, chr.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, chr.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, chr.Percent[0])
+
+	return b
+}

+ 35 - 0
chr_US/chr_US.go

@@ -114,3 +114,38 @@ func (chr *chr_US) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'chr_US' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (chr *chr_US) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(chr.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, chr.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, chr.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, chr.Percent[0])
+
+	return b
+}

+ 10 - 0
ckb/ckb.go

@@ -79,3 +79,13 @@ func (ckb *ckb) FmtNumber(num float64, v uint64) []byte {
 	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
 	return []byte(s)
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ckb' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ckb *ckb) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	return []byte(s)
+}

+ 10 - 0
ckb_IQ/ckb_IQ.go

@@ -79,3 +79,13 @@ func (ckb *ckb_IQ) FmtNumber(num float64, v uint64) []byte {
 	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
 	return []byte(s)
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ckb_IQ' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ckb *ckb_IQ) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	return []byte(s)
+}

+ 10 - 0
ckb_IR/ckb_IR.go

@@ -79,3 +79,13 @@ func (ckb *ckb_IR) FmtNumber(num float64, v uint64) []byte {
 	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
 	return []byte(s)
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'ckb_IR' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (ckb *ckb_IR) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	return []byte(s)
+}

+ 92 - 4
cmd/generate_resources.go

@@ -67,17 +67,23 @@ type translator struct {
 	PerMille       string
 	PerMilleLen    int
 	Currencies     string
-	// FmtNumberFunc  string
-	FmtNumberExists bool
-	FmtNumberPrefix string
-	FmtNumberSuffix string
 
+	// FmtNumber vars
+	FmtNumberExists            bool
 	FmtNumberGroupLen          int
 	FmtNumberSecondaryGroupLen int
 	FmtNumberMinDecimalLen     int
 
+	// FmtPercent vars
+	FmtPercentExists            bool
+	FmtPercentGroupLen          int
+	FmtPercentSecondaryGroupLen int
+	FmtPercentMinDecimalLen     int
+	FmtPercentLeft              bool
+
 	// calculation only fields
 	DecimalNumberFormat string
+	PercentNumberFormat string
 }
 
 func main() {
@@ -272,6 +278,13 @@ func postProcess(cldr *cldr.CLDR) {
 			}
 		}
 
+		if len(trans.PercentNumberFormat) == 0 {
+
+			if found {
+				trans.PercentNumberFormat = base.PercentNumberFormat
+			}
+		}
+
 		ldml := cldr.RawLDML(trans.Locale)
 
 		currencies := make([][]byte, len(globalCurrencies), len(globalCurrencies))
@@ -306,6 +319,7 @@ func postProcess(cldr *cldr.CLDR) {
 		trans.Currencies = fmt.Sprintf("%#v", currencies)
 
 		parseDecimalNumberFormat(trans)
+		parsePercentNumberFormat(trans)
 		// trans.FmtNumberFunc = parseDecimalNumberFormat(trans.DecimalNumberFormat, trans.BaseLocale)
 	}
 }
@@ -393,6 +407,16 @@ func preProcess(cldr *cldr.CLDR) {
 				}
 			}
 
+			if len(ldml.Numbers.PercentFormats) > 0 && len(ldml.Numbers.PercentFormats[0].PercentFormatLength) > 0 {
+
+				for _, dfl := range ldml.Numbers.PercentFormats[0].PercentFormatLength {
+					if len(dfl.Type) == 0 {
+						trans.PercentNumberFormat = dfl.PercentFormat[0].Pattern[0].Data()
+						break
+					}
+				}
+			}
+
 			// var decimalFormat, currencyFormat, currencyAccountingFormat, percentageFormat string
 
 			// if len(ldml.Numbers.DecimalFormats) > 0 && len(ldml.Numbers.DecimalFormats[0].DecimalFormatLength) > 0 {
@@ -431,6 +455,70 @@ func preProcess(cldr *cldr.CLDR) {
 	}
 }
 
+func parsePercentNumberFormat(trans *translator) (results string) {
+
+	if len(trans.PercentNumberFormat) == 0 {
+		return
+	}
+
+	trans.FmtPercentExists = true
+
+	formats := strings.SplitN(trans.PercentNumberFormat, ";", 2)
+
+	// if len(formats) > 1 {
+	// 	trans.FmtNumberHasNegativeFormat = true
+	// }
+
+	match := groupLenRegex.FindString(formats[0])
+	if len(match) > 0 {
+		trans.FmtPercentGroupLen = len(match) - 2
+	}
+
+	match = requiredDecimalRegex.FindString(formats[0])
+	if len(match) > 0 {
+		trans.FmtPercentMinDecimalLen = len(match) - 1
+	}
+
+	match = secondaryGroupLenRegex.FindString(formats[0])
+	if len(match) > 0 {
+		trans.FmtPercentSecondaryGroupLen = len(match) - 2
+	}
+
+	if formats[0][0] == '%' {
+		trans.FmtPercentLeft = true
+	}
+	// trans.FmtPercentLeft
+
+	// start := 0
+	// // prefix := ""
+
+	// // positive prefix
+	// for start = 0; start < len(formats[0]); start++ {
+	// 	if formats[0][start] == '#' || formats[0][start] == '0' {
+	// 		break
+	// 	}
+	// }
+
+	// // if start > 0 {
+	// // 	prefix = formats[0][:start]
+	// // }
+
+	// end := 0
+
+	// // positive prefix
+	// for end = len(formats[0]) - 1; end >= 0; end-- {
+	// 	if formats[0][end] == '#' || formats[0][end] == '0' {
+	// 		end++
+	// 		break
+	// 	}
+	// }
+
+	// fmt.Println(start)
+	// fmt.Println(end)
+
+	return
+}
+
 func parseDecimalNumberFormat(trans *translator) (results string) {
 
 	if len(trans.DecimalNumberFormat) == 0 {

+ 132 - 0
cmd/translator.tmpl

@@ -175,4 +175,136 @@ func({{ .BaseLocale }} *{{ .Locale }}) FmtNumber(num float64, v uint64) []byte {
 	{{ end -}}
 }
 
+// FmtPercent returns 'num' with digits/precision of 'v' for '{{ .Locale }}' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func({{ .BaseLocale }} *{{ .Locale }}) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	{{- if eq .FmtPercentExists true }}
+	{{- if gt .FmtPercentGroupLen 0 }}
+	l := len(s) + len({{ .BaseLocale }}.decimal) + len({{ .BaseLocale }}.group) * len(s[:len(s)-int(v)-1]) / {{ .FmtPercentGroupLen }}
+	count := 0
+	inWhole := v == 0
+	{{- if gt .FmtPercentSecondaryGroupLen 0}}
+	inSecondary := false
+	groupThreshold := {{ .FmtPercentGroupLen }}
+	{{ end -}}
+	{{ else }}
+	l := len(s) + len({{ .BaseLocale }}.decimal)
+	{{ end }}
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+
+			{{- if eq .DecimalLen 1 }}
+			b = append(b, {{ .BaseLocale }}.decimal[0])
+			{{- else }}
+			for j := len({{ .BaseLocale }}.decimal) - 1; j >= 0; j-- {
+				b = append(b, {{ .BaseLocale }}.decimal[j])
+			}
+			{{ end -}}
+			{{- if gt .FmtPercentGroupLen 0 }}
+			inWhole = true
+			{{ end }}
+			continue
+		}
+
+		{{ if gt .FmtPercentGroupLen 0 }}
+		if inWhole {
+
+			{{- if gt .FmtPercentSecondaryGroupLen 0}}
+			
+			if count == groupThreshold {
+				{{- if eq .GroupLen 1 }}
+				b = append(b, {{ .BaseLocale }}.group[0])
+				{{- else }}
+				for j := len({{ .BaseLocale }}.group) - 1; j >= 0; j-- {
+					b = append(b, {{ .BaseLocale }}.group[j])
+				}
+				{{ end }}
+				count = 1
+
+				if !inSecondary {
+					inSecondary = true
+					groupThreshold = {{ .FmtPercentSecondaryGroupLen }}
+				}
+			{{ else }}
+			if count == {{ .FmtPercentGroupLen }} {
+				{{- if eq .GroupLen 1 }}
+				b = append(b, {{ .BaseLocale }}.group[0])
+				{{- else }}
+				for j := len({{ .BaseLocale }}.group) - 1; j >= 0; j-- {
+					b = append(b, {{ .BaseLocale }}.group[j])
+				}
+				{{ end }}
+				count = 1
+			{{ end -}}
+			} else {
+				count++
+			}
+		}
+
+		{{ end }}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		{{- if eq .MinusLen 1 }}
+		b = append(b, {{ .BaseLocale }}.minus[0])
+		{{ else }}
+		for j := len({{ .BaseLocale }}.minus) - 1; j >= 0; j-- {
+			b = append(b, {{ .BaseLocale }}.minus[j])
+		}
+		{{ end -}}
+	}
+
+	{{ if eq .FmtPercentLeft true }}
+		{{- if eq .PercentLen 1 }}
+		b = append(b, {{ .BaseLocale }}.Percent[0])
+		{{ else }}
+		for j := len({{ .BaseLocale }}.percent) - 1; j >= 0; j-- {
+			b = append(b, {{ .BaseLocale }}.percent[j])
+		}
+		{{ end }}
+	{{ end }}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	{{ if gt .FmtPercentMinDecimalLen 0 }}
+	if int(v) < {{ .FmtPercentMinDecimalLen }} {
+
+		if v == 0 {
+			b = append(b, {{ .BaseLocale }}.decimal...)
+		}
+
+		for i := 0; i < {{ .FmtPercentMinDecimalLen }}-int(v); i++ {
+			b = append(b, '0')
+		}
+	}
+	{{ end }}
+
+	{{ if eq .FmtPercentLeft false }}
+		{{- if eq .PercentLen 1 }}
+		b = append(b, {{ .BaseLocale }}.Percent[0])
+		{{ else }}
+		for j := len({{ .BaseLocale }}.percent) - 1; j >= 0; j-- {
+			b = append(b, {{ .BaseLocale }}.percent[j])
+		}
+		{{ end }}
+	{{ end }}
+
+	return b
+	{{ else }}
+	return []byte(s)
+	{{ end -}}
+}
+
 {{ end }}

+ 42 - 0
cs/cs.go

@@ -160,3 +160,45 @@ func (cs *cs) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'cs' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (cs *cs) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(cs.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(cs.decimal) - 1; j >= 0; j-- {
+				b = append(b, cs.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(cs.minus) - 1; j >= 0; j-- {
+			b = append(b, cs.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(cs.percent) - 1; j >= 0; j-- {
+		b = append(b, cs.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
cs_CZ/cs_CZ.go

@@ -160,3 +160,45 @@ func (cs *cs_CZ) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'cs_CZ' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (cs *cs_CZ) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(cs.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(cs.decimal) - 1; j >= 0; j-- {
+				b = append(b, cs.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(cs.minus) - 1; j >= 0; j-- {
+			b = append(b, cs.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(cs.percent) - 1; j >= 0; j-- {
+		b = append(b, cs.percent[j])
+	}
+
+	return b
+}

+ 35 - 0
cu/cu.go

@@ -110,3 +110,38 @@ func (cu *cu) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'cu' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (cu *cu) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(cu.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, cu.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, cu.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, cu.Percent[0])
+
+	return b
+}

+ 35 - 0
cu_RU/cu_RU.go

@@ -110,3 +110,38 @@ func (cu *cu_RU) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'cu_RU' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (cu *cu_RU) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(cu.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, cu.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, cu.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, cu.Percent[0])
+
+	return b
+}

+ 42 - 0
cy/cy.go

@@ -190,3 +190,45 @@ func (cy *cy) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'cy' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (cy *cy) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(cy.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(cy.decimal) - 1; j >= 0; j-- {
+				b = append(b, cy.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(cy.minus) - 1; j >= 0; j-- {
+			b = append(b, cy.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(cy.percent) - 1; j >= 0; j-- {
+		b = append(b, cy.percent[j])
+	}
+
+	return b
+}

+ 42 - 0
cy_GB/cy_GB.go

@@ -190,3 +190,45 @@ func (cy *cy_GB) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'cy_GB' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (cy *cy_GB) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(cy.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			for j := len(cy.decimal) - 1; j >= 0; j-- {
+				b = append(b, cy.decimal[j])
+			}
+
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		for j := len(cy.minus) - 1; j >= 0; j-- {
+			b = append(b, cy.minus[j])
+		}
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	for j := len(cy.percent) - 1; j >= 0; j-- {
+		b = append(b, cy.percent[j])
+	}
+
+	return b
+}

+ 35 - 0
da/da.go

@@ -129,3 +129,38 @@ func (da *da) FmtNumber(num float64, v uint64) []byte {
 
 	return b
 }
+
+// FmtPercent returns 'num' with digits/precision of 'v' for 'da' and handles both Whole and Real numbers based on 'v'
+// returned as a []byte just in case the caller wishes to add more and can help
+// avoid allocations; otherwise just cast as string.
+// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
+func (da *da) FmtPercent(num float64, v uint64) []byte {
+
+	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
+	l := len(s) + len(da.decimal)
+
+	b := make([]byte, 0, l)
+
+	for i := len(s) - 1; i >= 0; i-- {
+
+		if s[i] == '.' {
+			b = append(b, da.decimal[0])
+			continue
+		}
+
+		b = append(b, s[i])
+	}
+
+	if num < 0 {
+		b = append(b, da.minus[0])
+	}
+
+	// reverse
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+
+	b = append(b, da.Percent[0])
+
+	return b
+}

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini