-
Notifications
You must be signed in to change notification settings - Fork 285
Add flatter data file structure #65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
nicksnyder
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! Sorry for the delay in reviewing.
Just a few comments.
i18n/bundle/bundle.go
Outdated
| var standardFormat []map[string]interface{} | ||
| err := unmarshal(filename, buf, &standardFormat) | ||
| if err == nil { | ||
| translations, err := parseStandardFormat(standardFormat) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can just be
return parseStandardFormat(standardFormat)
i18n/bundle/bundle.go
Outdated
| if err := unmarshal(filename, buf, &flatterFormat); err != nil { | ||
| return nil, err | ||
| } | ||
| translations, err := parseFlatterFormat(flatterFormat) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return parseFlatterFormat(flatterFormat)
i18n/bundle/bundle.go
Outdated
| return translations, nil | ||
| } | ||
|
|
||
| func parseFlatterFormat(data map[string]map[string]interface{}) ([]translation.Translation, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's just call this parseFlatFormat (and update files to be .flat.json)
i18n/bundle/bundle.go
Outdated
| if err := unmarshalFunc(buf, &translationsData); err != nil { | ||
| return nil, fmt.Errorf("failed to load %s because %s", filename, err) | ||
| } | ||
| return unmarshalFunc(buf, out) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add back the error message? It is nice to know which file the error happened in.
if err := unmarshalFunc(buf, &translationsData); err != nil {
return fmt.Errorf("failed to load %s because %s", filename, err)
}
i18n/translations_test.go
Outdated
|
|
||
| T, err := b.Tfunc("en-US") | ||
| if err != nil { | ||
| panic(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no reason to panic in a test, just fail the test
i18n/translations_test.go
Outdated
| initTestCases() | ||
| } | ||
|
|
||
| func initTestCases() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to create a separate method, just do this in init
i18n/translations_test.go
Outdated
| } | ||
|
|
||
| func initTestCases() { | ||
| b := bundle.New() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it doesn't appear necessary to create a bundle during initialization
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is used for creating a Tfunc and Tfunc is used for checking "d_days" in init (person_unread_email_count_timeframe).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. This is weird because you are reading the JSON file during init but testing other formats in the actual tests.
I would actually not try to do anything in init. Since it is just a test, it is fine to re-init the small array of test cases for each test.
i18n/translations_test.go
Outdated
| } | ||
|
|
||
| for _, tc := range testCases { | ||
| t.Run(tc.want, func(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using Run means tests don't compile on Go < 1.7. Can we do without?
| @@ -0,0 +1,34 @@ | |||
| { | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if this is a copy of en-us.all.json, can we call this en-us.all.flat.json?
| @@ -0,0 +1,25 @@ | |||
| program_greeting: | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
en-us.all.flat.yaml
31b1e16 to
72b2d34
Compare
| To use a different file format, write a parser for the format and add the parsed translations using [AddTranslation](https://godoc.org/github.com/nicksnyder/go-i18n/i18n#AddTranslation). | ||
| Flat Format |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to update the goi18n merge command to have an option to output the flat format before we advertise this on the main readme. Up to you whether you want to just remove the README update from this PR or update the merge command.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you offer to implement this? I propose to add a new boolean flag called -flat to output data in flat format
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
i18n/translations_test.go
Outdated
| } | ||
|
|
||
| func initTestCases() { | ||
| b := bundle.New() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. This is weird because you are reading the JSON file during init but testing other formats in the actual tests.
I would actually not try to do anything in init. Since it is just a test, it is fine to re-init the small array of test cases for each test.
|
I'm not familiar with the internals of the JSON and YAML packages. Do they return early if the data structure doesn't match the target interface? Can the caller avoid a double-unmarshal when using the flat format? |
|
@moorereason reading the docs of |
|
This change was motivated by another format, I think the current implementation is great as is. If there is a simple way to detect the format ala: isFlat := bytes.Contains(buf[:100], []byte("someflatidentifier")Then that would be great, but I would not add it if it adds complexity. |
|
The standard format could be detected this way: isStandard := bytes.Contains(data[:100], []byte("id")) && (bytes.Contains(data[:100], []byte("translation")) || bytes.Contains(data[:100], []byte("translations")))The problem could be if id will be more than ~95 bytes length, so it's not the right way. But actually this method only reduces complexity. |
|
@bep TOML doesn't support standard format layout. That's why we should add flat format |
|
I think, the simplest and right way to detect the format is built on the first byte. |
|
I know TOML isn't part of this PR (and it shouldn't be), but what would the equivalent TOML file look like?
This sounds right to me. |
|
9720d87 to
37787b5
Compare
|
So I updated merge command and made tests for it. What do you think about it? |
nicksnyder
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@BoGeM Thanks for updating! Just a few more comments and then I will merge it.
Can you also reply with what this will look like in TOML?
i18n/bundle/bundle.go
Outdated
| switch ext { | ||
| case ".json": | ||
| unmarshalFunc = json.Unmarshal | ||
| err = json.Unmarshal(buf, out) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just return json.Unmarshal(buf, out)
i18n/bundle/bundle.go
Outdated
| err = json.Unmarshal(buf, out) | ||
| case ".yaml": | ||
| unmarshalFunc = yaml.Unmarshal | ||
| err = yaml.Unmarshal(buf, out) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same
goi18n/merge_command.go
Outdated
| sort.Sort(translation.SortableByID(translations)) | ||
| buf, err := marshal(marshalInterface(translations)) | ||
|
|
||
| var iTranslations interface{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not a fan of this variable name. I would just avoid it though
var marshal func ([]translation.Translation) interface{}
if mc.flat {
marshal = marshalFlatInterface
} else {
marshal = marshalInterface
}
buf, err := mc.marshal(marshal(translations))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mc.marshal(marshal(translations)) - it's also very strange.
I offer to name it as conv2I or just convert.
|
@nicksnyder I've already told you: TOML doesn't support standard format layout. That's why we should add flat format. If user passes TOML translation file, it will be automatically parsed as flat format. So we don't need to detect the format for TOML. At least I will implement like that |
|
I know TOML doesn't support standard format. I want to know what it will
look like in the flat format.
…On Sat, Mar 18, 2017 at 10:08 PM Albert Nigmatzianov < ***@***.***> wrote:
@nicksnyder <https://github.com/nicksnyder> I've already told you: TOML
doesn't support standard format layout. That's why we should add flat
format. If user passes TOML translation file, it will be automatically
parsed as flat format. So we don't need to detect the format for TOML. At
least I will implement like that
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#65 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAuEUMqLtMvN9VlVaeNzwl0laCPU4Tc-ks5rnLhjgaJpZM4MGn4u>
.
|
func isStandardFormat(ext string, buf []byte) bool {
if ext == ".toml" {
return false
}
firstRune := rune(buf[0])
if (ext == ".json" && firstRune == '[') || (ext == ".yaml" && firstRune == '-') {
return true
}
return false
} |
|
Sorry if I wasn't clear. I want to know what |
|
Oh sorry. I thought, you asked me about detection of TOML 😅 [program_greeting]
other = "Hello world"
[person_greeting]
other = "Hello {{.Person}}"
[my_height_in_meters]
one = "I am {{.Count}} meter tall."
other = "I am {{.Count}} meters tall."
[your_unread_email_count]
one = "You have {{.Count}} unread email."
other = "You have {{.Count}} unread emails."
[person_unread_email_count]
one = "{{.Person}} has {{.Count}} unread email."
other = "{{.Person}} has {{.Count}} unread emails."
[person_unread_email_count_timeframe]
one = "{{.Person}} has {{.Count}} unread email in the past {{.Timeframe}}."
other = "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
[d_days]
one = "{{.Count}} day."
other = "{{.Count}} days." |
Fixes #62
Updates #61
TODO:
Please leave your opinions and comments.
/cc @bep @moorereason @nicksnyder