[Feature/51] :: standardize country specific struct naming convention#52
Conversation
…ror internationalization
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughRefactors mocai from global state to dependency-injected instance usage: introduces NewMocker(lang,isFormatted,rnd) returning a configured Mocker that lazily generates entities; generators and translations now accept explicit lang and RandSource; many error messages standardized and several struct fields/return signatures changed. Changes
Sequence Diagram(s)sequenceDiagram
participant Dev as Developer/Client
participant Mocker as Mocker Instance
participant Trans as Translations
participant RNG as RandSource
participant Entity as Entity Generator (Person/CPF/...)
Dev->>Mocker: call NewMocker(lang,isFormatted,rnd)
Note right of Mocker: stores config (lang, formatted, rnd)
Dev->>Mocker: m.NewPerson()
Mocker->>Trans: GetList(lang,"first_names"/"last_names")
Mocker->>RNG: Intn(...)
Mocker->>Entity: generatePerson(lang,isFormatted,rnd)
Entity->>Trans: Get/format translations (e.g., gender, messages)
Entity->>RNG: Intn(...) for digits/age/selection
Entity-->>Mocker: *Person / error (wrapped with Trans.Get message)
Mocker-->>Dev: returns *Person / error
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment Tip You can get early access to new features in CodeRabbit.Enable the |
There was a problem hiding this comment.
Actionable comments posted: 12
🧹 Nitpick comments (3)
pkg/mocai/entities/gender/gender.go (1)
46-48: Consider centralizingdefaultRandSourcehelper.This
defaultRandSourcefunction is duplicated inphone/generator.goand likely other entity generators. To avoid drift and simplify maintenance, consider moving it to a shared location (e.g.,translationspackage or acommonpackage).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/mocai/entities/gender/gender.go` around lines 46 - 48, The helper defaultRandSource (returns translations.RandSource) is duplicated across generators (e.g., gender.go and phone/generator.go); move a single implementation into a shared package (suggest translations or a new common package), export it (e.g., NewDefaultRandSource or DefaultRandSource) and replace/remove the local copies in gender.go and phone/generator.go, updating imports and callers to use the centralized symbol to prevent drift and simplify maintenance.pkg/mocai/entities/phone/generator.go (1)
40-42: DuplicatedefaultRandSourcehelper.This is identical to the implementation in
gender/gender.go. As noted earlier, consider centralizing this to avoid duplication.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/mocai/entities/phone/generator.go` around lines 40 - 42, The function defaultRandSource in generator.go is a duplicate of the same helper in the gender package; remove this duplicate and instead use a single shared helper (e.g., move the implementation into the translations package as translations.DefaultRandSource or a new util package) and update callers to call that shared symbol; ensure the symbol name and signature match existing callers so you only change the implementation location (keep the function name defaultRandSource or provide translations.DefaultRandSource and replace references to defaultRandSource with the new shared symbol across generator.go and gender code).pkg/mocai/translations/translations.go (1)
18-30: Don't expose the registry's backing slices.
RegisterListstores caller-owned slices directly andGetListreturns them directly. Any caller that mutates the returned slice can corrupt global translation data for later lookups, and that happens outsidemu.♻️ Suggested hardening
func RegisterList(lang string, messages map[string][]string) { if lang == "" || messages == nil { return } mu.Lock() defer mu.Unlock() if registryList[lang] == nil { registryList[lang] = make(map[string][]string) } for key, values := range messages { - registryList[lang][key] = values + registryList[lang][key] = append([]string(nil), values...) } } @@ func GetList(lang, key string) []string { if lang == "" || key == "" { return nil } mu.RLock() defer mu.RUnlock() if val, ok := registryList[lang][key]; ok { - return val + return append([]string(nil), val...) } return nil }Also applies to: 61-72
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/mocai/translations/translations.go` around lines 18 - 30, RegisterList currently stores caller-owned slices directly into the shared registry and GetList returns those same slices, allowing external mutation to corrupt global state; change RegisterList to copy each incoming slice before assigning it into registryList (copy values into a new []string) and ensure GetList returns a copy of the stored slice(s) (or copies the map and each slice) so callers never get direct references to the registry's backing arrays; refer to RegisterList, GetList, registryList and mu when updating the logic and preserve mu locking semantics while performing the copies.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@pkg/mocai/entities/address/generator.go`:
- Around line 35-39: The generator currently fetches states and UFs
independently which can create invalid state↔UF combos; change the logic to
perform a single paired lookup from the translations map that represents
state→uf (use the existing state→UF mapping in translations/pt_br.go) and then
select one random pair to populate both the State and UF fields. Replace the
separate translations.GetList(lang, "address_state") and
translations.GetList(lang, "address_uf") calls with a single map/list lookup
(e.g., a stateToUf map or paired list) and update the code paths that set State
and UF (including the usage around lines referenced 63-64) to consume the chosen
pair so the two values remain consistent.
- Around line 34-35: generateAddress currently dereferences rnd (type
translations.RandSource) without checking for nil, causing NewAddress("ptbr",
nil) to panic; add a nil check at the top of generateAddress and if rnd == nil
assign the same default/fallback RandSource used by the other generators (e.g.,
rnd = translations.DefaultRand() or the package's default RandSource
initializer) before any calls to rnd.Intn or other methods so subsequent code
using rnd (and similar fixes in the other generator functions referenced around
lines 60-69) will not panic.
In `@pkg/mocai/entities/certificate/countries/brazilian_certificates.go`:
- Around line 86-90: The helpers for birth/marriage/death are dropping the
caller-provided language because generateCertificateCustom sets a hard default
and callers don't forward the variadic lang; update the helper functions (the
birth/marriage/death certificate generators that call generateCertificateCustom)
to forward their lang... variadic argument into generateCertificateCustom so the
chosen language reaches the translation layer, and normalize the internal
default in generateCertificateCustom from "pt_br" to "ptbr" to match the rest of
the codebase (examples/mocker uses "ptbr"). Ensure all other calls in this file
(including the calls around lines 142-171) also pass through the lang parameter
unchanged.
In `@pkg/mocai/entities/certificate/generator.go`:
- Around line 18-23: The wrapper generateCertificate(lang string, formatted
bool, rnd translations.RandSource) accepts a language but downstream code still
hardcodes pt_br; update countries.NewBrazilCertificatesCustom and the
Brazil-specific helper functions in pkg/mocai/entities/certificate/countries
(including generateCertificateCustom, the birth/marriage/death helper functions)
to accept and forward the lang parameter instead of defaulting to "pt_br", and
ensure NewCertificate (or equivalent constructor used in those helpers) is
called with the passed lang so translations are correctly used when
generateCertificate is invoked with non-default languages.
In `@pkg/mocai/entities/company/countries/brazilian_company.go`:
- Around line 17-30: GenerateBrazilianCompany advertises an injected random
source (rnd) but still calls cnpj.GenerateCNPJ(formatted) which ignores rnd;
update GenerateBrazilianCompany so CNPJ generation uses the same rnd (either by
calling a cnpj function that accepts a RandSource if available, e.g.,
cnpj.GenerateCNPJWithRand(rnd, formatted), or implement a small helper in this
package that generates/format CNPJ digits using rnd.Intn and the same
checksum/format logic) and replace the cnpj.GenerateCNPJ call with that
rnd-aware generator so the entire payload is reproducible via rnd.
In `@pkg/mocai/entities/nationalid/countries/brazilian_national_id.go`:
- Around line 18-23: The default language key in NewRGCustom is incorrect
("pt_br") causing untranslated metadata; update the default to the registered
key "ptbr" and ensure any fallback logic that passes the language to
generateBrazilianNationalIDCustom uses "ptbr" when len(lang)==0 or lang[0]==""
so callers that omit lang receive Brazilian Portuguese translations.
In `@pkg/mocai/entities/nationalid/generator.go`:
- Around line 17-20: The function generateNationalID currently declares an error
return but always returns nil; update its signature to remove the error return
so it returns only (*NationalID) and update the return statement to return the
value directly; locate generateNationalID and the construction using
countries.NewRGCustom and change any callers if necessary to handle the
single-return value from generateNationalID/NationalID (no error).
In `@pkg/mocai/entities/phone/generator.go`:
- Around line 30-33: The condition checking number == "" is unreachable because
number is produced by fmt.Sprintf("9%08d", ...), so remove the dead check and
only validate the meaningful condition (areaCode == ""); alternatively, if you
want defensive validation, replace number == "" with a format/length check
(e.g., len(number) != 9 or a regex) before returning ErrGeneratingPhone and the
translations.Get(lang, "error_generating_phone") error; update the condition in
the phone generation function where variables number and areaCode are used (and
the error return that references ErrGeneratingPhone and translations.Get)
accordingly.
In `@pkg/mocai/mocker.go`:
- Around line 19-23: The Mocker struct holds a shared translations.RandSource
(rnd) and exposes it via GetRand(), making Mocker mutable and unsafe for
concurrent reuse; remove direct exposure and either wrap rnd in a mutex-backed
implementation of translations.RandSource or allocate a fresh RandSource per
operation and stop returning it from GetRand(); update callers that currently
pass m.rnd into generators (look for uses in methods named GetRand, NewMocker,
and generator constructors) to accept a thread-safe wrapper or a newly created
source per call so the shared math/rand state is never concurrently accessed or
externally advanced.
In `@pkg/mocai/translations/pt_br.go`:
- Line 70: The translation key "invalid_vital_records_service number" has a
space that breaks the snake_case convention; update the key to
"invalid_vital_records_service_number" (preserving the Portuguese value "número
de serviço de registros vitais inválido") so lookups using
invalid_vital_records_service_number work correctly in the code paths that
reference that key.
- Around line 31-44: RegisterList for "ptbr" is missing the "phone_area_code"
entry, so calls to GetList("ptbr","phone_area_code") return nil; add
"phone_area_code" to the RegisterList map in pt_br.go (the same place
Register("ptbr","phone_area_code", ...) is set) and populate it with the slice
source used for single-value Register (or the underlying slice from phone_mocks
if available) so registryList contains that key; ensure you reference
RegisterList("ptbr", ...) and the existing Register("ptbr","phone_area_code",
...) to keep values consistent with GetList and registryList behavior.
In `@pkg/mocai/translations/translations.go`:
- Around line 18-31: RegisterList split left PT-BR list-backed keys registered
via Register() unreachable by GetList, causing empty slices; fix by adding a
compatibility path so GetList (or RegisterList) considers both registryList and
the older registry map: update GetList to merge entries from registryList[lang]
and registry[lang] (or, alternatively, move the pt_br registrations into
RegisterList) so keys like company_name, person_first_name_*, person_last_name,
phone_area_code are returned; reference the functions RegisterList, GetList,
Register and the maps registryList and registry when making the change.
---
Nitpick comments:
In `@pkg/mocai/entities/gender/gender.go`:
- Around line 46-48: The helper defaultRandSource (returns
translations.RandSource) is duplicated across generators (e.g., gender.go and
phone/generator.go); move a single implementation into a shared package (suggest
translations or a new common package), export it (e.g., NewDefaultRandSource or
DefaultRandSource) and replace/remove the local copies in gender.go and
phone/generator.go, updating imports and callers to use the centralized symbol
to prevent drift and simplify maintenance.
In `@pkg/mocai/entities/phone/generator.go`:
- Around line 40-42: The function defaultRandSource in generator.go is a
duplicate of the same helper in the gender package; remove this duplicate and
instead use a single shared helper (e.g., move the implementation into the
translations package as translations.DefaultRandSource or a new util package)
and update callers to call that shared symbol; ensure the symbol name and
signature match existing callers so you only change the implementation location
(keep the function name defaultRandSource or provide
translations.DefaultRandSource and replace references to defaultRandSource with
the new shared symbol across generator.go and gender code).
In `@pkg/mocai/translations/translations.go`:
- Around line 18-30: RegisterList currently stores caller-owned slices directly
into the shared registry and GetList returns those same slices, allowing
external mutation to corrupt global state; change RegisterList to copy each
incoming slice before assigning it into registryList (copy values into a new
[]string) and ensure GetList returns a copy of the stored slice(s) (or copies
the map and each slice) so callers never get direct references to the registry's
backing arrays; refer to RegisterList, GetList, registryList and mu when
updating the logic and preserve mu locking semantics while performing the
copies.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: df89a63b-74b0-48fb-80e5-1aa39322e81c
📒 Files selected for processing (29)
README.mddocs/localization/pt/README-PT.mdexamples/mocker/main.gopkg/mocai/entities/address/generator.gopkg/mocai/entities/certificate/countries/brazilian_certificates.gopkg/mocai/entities/certificate/countries/errors.gopkg/mocai/entities/certificate/generator.gopkg/mocai/entities/cnpj/errors.gopkg/mocai/entities/company/countries/brazilian_company.gopkg/mocai/entities/company/countries/errors.gopkg/mocai/entities/company/countries/generator_test.gopkg/mocai/entities/company/generator.gopkg/mocai/entities/cpf/errors.gopkg/mocai/entities/cpf/generator.gopkg/mocai/entities/cpf/validator.gopkg/mocai/entities/gender/errors.gopkg/mocai/entities/gender/gender.gopkg/mocai/entities/nationalid/countries/brazilian_national_id.gopkg/mocai/entities/nationalid/countries/errors.gopkg/mocai/entities/nationalid/generator.gopkg/mocai/entities/person/errors.gopkg/mocai/entities/person/generator.gopkg/mocai/entities/phone/errors.gopkg/mocai/entities/phone/generator.gopkg/mocai/entities/voteregistration/countries/brazilian_vote_registration.gopkg/mocai/entities/voteregistration/generator.gopkg/mocai/mocker.gopkg/mocai/translations/pt_br.gopkg/mocai/translations/translations.go
| func generateAddress(lang string, rnd translations.RandSource) (*Address, error) { | ||
| streets := translations.GetList(lang, "address_street") |
There was a problem hiding this comment.
Handle nil RandSource before the first Intn call.
generateAddress dereferences rnd unconditionally, so NewAddress("ptbr", nil) panics. The new API surface also allows nil, so this needs the same fallback the other generators already have.
🛠️ Suggested fix
import (
"fmt"
+ "math/rand"
"strings"
+ "time"
"github.com/brazzcore/mocai/pkg/mocai/translations"
)
func generateAddress(lang string, rnd translations.RandSource) (*Address, error) {
+ if rnd == nil {
+ rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
+ }
streets := translations.GetList(lang, "address_street")Also applies to: 60-69
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/entities/address/generator.go` around lines 34 - 35,
generateAddress currently dereferences rnd (type translations.RandSource)
without checking for nil, causing NewAddress("ptbr", nil) to panic; add a nil
check at the top of generateAddress and if rnd == nil assign the same
default/fallback RandSource used by the other generators (e.g., rnd =
translations.DefaultRand() or the package's default RandSource initializer)
before any calls to rnd.Intn or other methods so subsequent code using rnd (and
similar fixes in the other generator functions referenced around lines 60-69)
will not panic.
| streets := translations.GetList(lang, "address_street") | ||
| cities := translations.GetList(lang, "address_city") | ||
| states := translations.GetList(lang, "address_state") | ||
| ufs := translations.GetList(lang, "address_uf") | ||
| zips := translations.GetList(lang, "address_zip") |
There was a problem hiding this comment.
Keep State and UF generated as a pair.
Selecting state and uf from independent lists can emit impossible combinations. The source data already has a state→UF relationship in pkg/mocai/translations/pt_br.go, so this should come from one paired lookup instead of two unrelated random picks.
Also applies to: 63-64
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/entities/address/generator.go` around lines 35 - 39, The generator
currently fetches states and UFs independently which can create invalid state↔UF
combos; change the logic to perform a single paired lookup from the translations
map that represents state→uf (use the existing state→UF mapping in
translations/pt_br.go) and then select one random pair to populate both the
State and UF fields. Replace the separate translations.GetList(lang,
"address_state") and translations.GetList(lang, "address_uf") calls with a
single map/list lookup (e.g., a stateToUf map or paired list) and update the
code paths that set State and UF (including the usage around lines referenced
63-64) to consume the chosen pair so the two values remain consistent.
| func generateCertificateCustom(rnd translations.RandSource, formatted bool, certificateType int, lang ...string) (*BaseCertificate, error) { | ||
| l := "pt_br" | ||
| if len(lang) > 0 && lang[0] != "" { | ||
| l = lang[0] | ||
| } |
There was a problem hiding this comment.
lang is currently dropped before the certificate helpers reach the translation layer.
The birth/marriage/death helpers call generateCertificateCustom without forwarding lang, so that function always falls back to its internal default. That default is pt_br, while the rest of the PR uses ptbr (for example examples/mocker/main.go:15), so localized error paths from these helpers fall back to raw keys even when callers pass a language.
🔧 Suggested fix
-func generateCertificateCustom(rnd translations.RandSource, formatted bool, certificateType int, lang ...string) (*BaseCertificate, error) {
- l := "pt_br"
- if len(lang) > 0 && lang[0] != "" {
- l = lang[0]
- }
+func generateCertificateCustom(rnd translations.RandSource, formatted bool, certificateType int, lang string) (*BaseCertificate, error) {
+ if lang == "" {
+ lang = "ptbr"
+ }
@@
-base, err := generateCertificateCustom(rnd, formatted, brazilianBirthCertificateType)
+base, err := generateCertificateCustom(rnd, formatted, brazilianBirthCertificateType, lang)
@@
-base, err := generateCertificateCustom(rnd, formatted, brazilianMarriageCertificateType)
+base, err := generateCertificateCustom(rnd, formatted, brazilianMarriageCertificateType, lang)
@@
-base, err := generateCertificateCustom(rnd, formatted, brazilianDeathCertificateType)
+base, err := generateCertificateCustom(rnd, formatted, brazilianDeathCertificateType, lang)Also applies to: 142-171
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/entities/certificate/countries/brazilian_certificates.go` around
lines 86 - 90, The helpers for birth/marriage/death are dropping the
caller-provided language because generateCertificateCustom sets a hard default
and callers don't forward the variadic lang; update the helper functions (the
birth/marriage/death certificate generators that call generateCertificateCustom)
to forward their lang... variadic argument into generateCertificateCustom so the
chosen language reaches the translation layer, and normalize the internal
default in generateCertificateCustom from "pt_br" to "ptbr" to match the rest of
the codebase (examples/mocker uses "ptbr"). Ensure all other calls in this file
(including the calls around lines 142-171) also pass through the lang parameter
unchanged.
| func generateCertificate(lang string, formatted bool, rnd translations.RandSource) (*Certificate, error) { | ||
| createdBrazilianCertificates, err := countries.NewBrazilCertificatesCustom(lang, formatted, rnd) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| return &Certificate{BrazilianCertificates: createdBrazilianCertificates}, nil | ||
| return &Certificate{Brazil: createdBrazilianCertificates}, nil |
There was a problem hiding this comment.
The new lang parameter is not fully honored yet.
This wrapper advertises custom-language generation, but the supplied context for pkg/mocai/entities/certificate/countries/brazilian_certificates.go still defaults generateCertificateCustom to pt_br, and the birth/marriage/death helpers there do not forward lang. NewCertificate("ptbr", ...) can therefore still miss translations even though Line 19 accepts the caller’s language.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/entities/certificate/generator.go` around lines 18 - 23, The
wrapper generateCertificate(lang string, formatted bool, rnd
translations.RandSource) accepts a language but downstream code still hardcodes
pt_br; update countries.NewBrazilCertificatesCustom and the Brazil-specific
helper functions in pkg/mocai/entities/certificate/countries (including
generateCertificateCustom, the birth/marriage/death helper functions) to accept
and forward the lang parameter instead of defaulting to "pt_br", and ensure
NewCertificate (or equivalent constructor used in those helpers) is called with
the passed lang so translations are correctly used when generateCertificate is
invoked with non-default languages.
| number := fmt.Sprintf("9%08d", rnd.Intn(100000000)) | ||
| if areaCode == "" || number == "" { | ||
| return nil, fmt.Errorf("%s: missing required data (areaCode: %s, number: %s)", | ||
| ErrGeneratingPhone, areaCode, number) | ||
| return nil, fmt.Errorf("%w, %s", ErrGeneratingPhone, translations.Get(lang, "error_generating_phone")) | ||
| } |
There was a problem hiding this comment.
Unreachable condition: number can never be empty.
The number == "" check on line 31 is always false because fmt.Sprintf("9%08d", ...) always produces a 9-character string. Consider removing this dead branch or, if validating against unexpected formats, checking for a more meaningful condition.
♻️ Proposed simplification
number := fmt.Sprintf("9%08d", rnd.Intn(100000000))
- if areaCode == "" || number == "" {
+ if areaCode == "" {
return nil, fmt.Errorf("%w, %s", ErrGeneratingPhone, translations.Get(lang, "error_generating_phone"))
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/entities/phone/generator.go` around lines 30 - 33, The condition
checking number == "" is unreachable because number is produced by
fmt.Sprintf("9%08d", ...), so remove the dead check and only validate the
meaningful condition (areaCode == ""); alternatively, if you want defensive
validation, replace number == "" with a format/length check (e.g., len(number)
!= 9 or a regex) before returning ErrGeneratingPhone and the
translations.Get(lang, "error_generating_phone") error; update the condition in
the phone generation function where variables number and areaCode are used (and
the error return that references ErrGeneratingPhone and translations.Get)
accordingly.
| type Mocker struct { | ||
| Address *address.Address | ||
| Certificate *certificate.Certificate | ||
| Company *company.Company | ||
| Gender *gender.Gender | ||
| NationalID *nationalid.NationalID | ||
| Person *person.Person | ||
| Phone *phone.Phone | ||
| VoteRegistration *voteregistration.VoteRegistration | ||
|
|
||
| formatted bool | ||
| lang string | ||
| formatted bool | ||
| rnd translations.RandSource | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Is Go's math/rand.Rand safe for concurrent use by multiple goroutines, and are only the package-level math/rand functions concurrency-safe?
💡 Result:
No, Go's math/rand.Rand is not safe for concurrent use by multiple goroutines. It must be used by a single goroutine at a time; sharing among multiple goroutines requires synchronization such as a mutex. Yes, the package-level math/rand functions (top-level functions like Int, Float64, etc.) are safe for concurrent use by multiple goroutines, as they use a synchronized default Source.
Citations:
- 1: https://pkg.go.dev/math/rand@go1.25.5
- 2: https://pkg.go.dev/math/rand
- 3: https://go.dev/src/math/rand/rand.go
🏁 Script executed:
cd pkg/mocai && head -100 mocker.go | cat -nRepository: brazzcore/mocai
Length of output: 3776
The shared RNG makes Mocker mutable and unsafe to reuse concurrently.
This instance keeps one RandSource, passes it into every generator, and then exposes it again via GetRand(). When the default is *rand.Rand, a single mocker used from multiple goroutines will race inside math/rand, and external callers can advance the sequence through GetRand(), which undercuts the "immutable instance" contract. Consider wrapping the source in a mutex-backed RandSource or creating a fresh source per call, and avoid returning it directly.
Also applies to: 25-39, 87-89
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/mocker.go` around lines 19 - 23, The Mocker struct holds a shared
translations.RandSource (rnd) and exposes it via GetRand(), making Mocker
mutable and unsafe for concurrent reuse; remove direct exposure and either wrap
rnd in a mutex-backed implementation of translations.RandSource or allocate a
fresh RandSource per operation and stop returning it from GetRand(); update
callers that currently pass m.rnd into generators (look for uses in methods
named GetRand, NewMocker, and generator constructors) to accept a thread-safe
wrapper or a newly created source per call so the shared math/rand state is
never concurrently accessed or externally advanced.
| // registers complete lists for use in mocks | ||
| RegisterList("ptbr", map[string][]string{ | ||
| "address_street": address_mocks.Streets, | ||
| "address_city": address_mocks.Cities, | ||
| "address_state": address_mocks.States, | ||
| "address_uf": func() []string { | ||
| ufs := make([]string, 0, len(address_mocks.UFs)) | ||
| for _, uf := range address_mocks.UFs { | ||
| ufs = append(ufs, uf) | ||
| } | ||
| return ufs | ||
| }(), | ||
| "address_zip": address_mocks.ZIPCodes, | ||
| }) |
There was a problem hiding this comment.
Missing phone_area_code registration in RegisterList.
The phone_area_code key is registered only via Register() at line 63 as a single random string, but not via RegisterList(). Based on the GetList() implementation in translations.go (lines 62-72), any code calling GetList("ptbr", "phone_area_code") will receive nil since the key doesn't exist in registryList.
Add phone_area_code to the list registrations:
Proposed fix
// registers complete lists for use in mocks
RegisterList("ptbr", map[string][]string{
"address_street": address_mocks.Streets,
"address_city": address_mocks.Cities,
"address_state": address_mocks.States,
"address_uf": func() []string {
ufs := make([]string, 0, len(address_mocks.UFs))
for _, uf := range address_mocks.UFs {
ufs = append(ufs, uf)
}
return ufs
}(),
"address_zip": address_mocks.ZIPCodes,
+ "phone_area_code": phone_mocks.AreaCodes,
})📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // registers complete lists for use in mocks | |
| RegisterList("ptbr", map[string][]string{ | |
| "address_street": address_mocks.Streets, | |
| "address_city": address_mocks.Cities, | |
| "address_state": address_mocks.States, | |
| "address_uf": func() []string { | |
| ufs := make([]string, 0, len(address_mocks.UFs)) | |
| for _, uf := range address_mocks.UFs { | |
| ufs = append(ufs, uf) | |
| } | |
| return ufs | |
| }(), | |
| "address_zip": address_mocks.ZIPCodes, | |
| }) | |
| // registers complete lists for use in mocks | |
| RegisterList("ptbr", map[string][]string{ | |
| "address_street": address_mocks.Streets, | |
| "address_city": address_mocks.Cities, | |
| "address_state": address_mocks.States, | |
| "address_uf": func() []string { | |
| ufs := make([]string, 0, len(address_mocks.UFs)) | |
| for _, uf := range address_mocks.UFs { | |
| ufs = append(ufs, uf) | |
| } | |
| return ufs | |
| }(), | |
| "address_zip": address_mocks.ZIPCodes, | |
| "phone_area_code": phone_mocks.AreaCodes, | |
| }) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/translations/pt_br.go` around lines 31 - 44, RegisterList for
"ptbr" is missing the "phone_area_code" entry, so calls to
GetList("ptbr","phone_area_code") return nil; add "phone_area_code" to the
RegisterList map in pt_br.go (the same place Register("ptbr","phone_area_code",
...) is set) and populate it with the slice source used for single-value
Register (or the underlying slice from phone_mocks if available) so registryList
contains that key; ensure you reference RegisterList("ptbr", ...) and the
existing Register("ptbr","phone_area_code", ...) to keep values consistent with
GetList and registryList behavior.
| "invalid_certificate": "certidão inválida", | ||
| "invalid_vital_records_office_number": "número do cartório de registros civis inválido", | ||
| "invalid_archive_number": "número do arquivo inválido", | ||
| "invalid_vital_records_service number": "número de serviço de registros vitais inválido", |
There was a problem hiding this comment.
Typo: inconsistent key naming with space instead of underscore.
The key "invalid_vital_records_service number" contains a space before "number" instead of an underscore. This breaks the snake_case naming convention used by all other keys.
Proposed fix
- "invalid_vital_records_service number": "número de serviço de registros vitais inválido",
+ "invalid_vital_records_service_number": "número de serviço de registros vitais inválido",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "invalid_vital_records_service number": "número de serviço de registros vitais inválido", | |
| "invalid_vital_records_service_number": "número de serviço de registros vitais inválido", |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/translations/pt_br.go` at line 70, The translation key
"invalid_vital_records_service number" has a space that breaks the snake_case
convention; update the key to "invalid_vital_records_service_number" (preserving
the Portuguese value "número de serviço de registros vitais inválido") so
lookups using invalid_vital_records_service_number work correctly in the code
paths that reference that key.
| // RegisterList records lists of translations | ||
| func RegisterList(lang string, messages map[string][]string) { | ||
| if lang == "" || messages == nil { | ||
| return | ||
| } | ||
|
|
||
| mu.Lock() | ||
| defer mu.Unlock() | ||
|
|
||
| if registry[lang] == nil { | ||
| registry[lang] = make(map[string]string) | ||
| if registryList[lang] == nil { | ||
| registryList[lang] = make(map[string][]string) | ||
| } | ||
| for key, value := range messages { | ||
| registry[lang][key] = value | ||
| for key, values := range messages { | ||
| registryList[lang][key] = values | ||
| } | ||
| } |
There was a problem hiding this comment.
This split breaks the current PT-BR list-backed datasets.
GetList only reads registryList, but the current pkg/mocai/translations/pt_br.go:51-87 still registers keys like company_name, person_first_name_*, person_last_name, and phone_area_code through Register(). That leaves every GetList("ptbr", ...) caller with an empty slice and causes generators like company, person, and phone to fail immediately. Either migrate those registrations in the same change or add a compatibility path here.
Also applies to: 61-72
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/translations/translations.go` around lines 18 - 31, RegisterList
split left PT-BR list-backed keys registered via Register() unreachable by
GetList, causing empty slices; fix by adding a compatibility path so GetList (or
RegisterList) considers both registryList and the older registry map: update
GetList to merge entries from registryList[lang] and registry[lang] (or,
alternatively, move the pt_br registrations into RegisterList) so keys like
company_name, person_first_name_*, person_last_name, phone_area_code are
returned; reference the functions RegisterList, GetList, Register and the maps
registryList and registry when making the change.
…e for company and cnpj generation
Summary by CodeRabbit
New Features
Documentation
Refactor