-
Notifications
You must be signed in to change notification settings - Fork 267
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
Add flatter data file structure #65
Conversation
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
} | ||
translations = append(translations, t) | ||
} | ||
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?
goi18n/testdata/en-us.flatter.json
Outdated
@@ -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
?
goi18n/testdata/en-us.flatter.yaml
Outdated
@@ -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
@@ -118,6 +118,49 @@ Here is an example of the default file format that go-i18n supports: | |||
|
|||
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? |
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
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
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