marhali / easy-i18n

This is a IntelliJ IDE based plugin for internationalization. Supports the most common translation file types.
MIT License
80 stars 25 forks source link

YMAL parser taking every string yes, no, on or off as boolean. #248

Open levalup opened 1 year ago

levalup commented 1 year ago

Version: Easy I18n(4.4.1)

I was using yml config like this:

enum:
  bool:
    yes: yes
    no: no
    on: on
    off: off

This causes the following error. This looks like taking the string yes, no, on or off as boolean.

If I change locale file to:

enum:
  bool:
    'yes': yes
    'no': no
    'on': on
    'off': off

Then I got table like this:

Key en-US
enum.bool.no false
enum.bool.off false
enum.bool.on true
enum.bool.yes true

Well, the YAML parser taking every string yes, no, on or off as boolean.

I don't think it's good idea to keep default SpringBoot (or other tool) behaviour to parse locale file.

At least it should not crash, and then remind users that special strings should be enclosed in single quotation marks(').

The yaml locale file work fine in my project with vue-i18n, before I change anything.

Error log

An error occurred while processing translation files. 
Config: SINGLE => YML (*.yml) 
Path: D:\Workspace\Development\Project\locales
Please check examples at https://github.com/marhali/easy-i18n before reporting an issue!

java.io.IOException: TranslationFile{virtualFile=file://D:/Workspace/Development/Project/locales/en-US.yml, locale='en-US', namespace='null'}

class java.lang.Boolean cannot be cast to class java.lang.String (java.lang.Boolean and java.lang.String are in module java.base of loader 'bootstrap')
    at de.marhali.easyi18n.io.IOHandler.read(IOHandler.java:83)
    at de.marhali.easyi18n.DataStore.lambda$loadFromPersistenceLayer$0(DataStore.java:54)
    at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:872)
    at de.marhali.easyi18n.DataStore.loadFromPersistenceLayer(DataStore.java:52)
    at de.marhali.easyi18n.InstanceManager.reload(InstanceManager.java:76)
    at de.marhali.easyi18n.service.FileChangeListener$1.lambda$afterVfsChange$0(FileChangeListener.java:59)
    at com.intellij.openapi.application.TransactionGuardImpl.runWithWritingAllowed(TransactionGuardImpl.java:209)
    at com.intellij.openapi.application.TransactionGuardImpl.access$100(TransactionGuardImpl.java:21)
    at com.intellij.openapi.application.TransactionGuardImpl$1.run(TransactionGuardImpl.java:191)
    at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:838)
    at com.intellij.openapi.application.impl.ApplicationImpl$3.run(ApplicationImpl.java:454)
    at com.intellij.openapi.application.impl.FlushQueue.doRun(FlushQueue.java:74)
    at com.intellij.openapi.application.impl.FlushQueue.runNextEvent(FlushQueue.java:114)
    at com.intellij.openapi.application.impl.FlushQueue.flushNow(FlushQueue.java:36)
    at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:779)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:730)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:724)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:749)
    at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:909)
    at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:756)
    at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$5(IdeEventQueue.java:437)
    at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:787)
    at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$6(IdeEventQueue.java:436)
    at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:105)
    at com.intellij.ide.IdeEventQueue.performActivity(IdeEventQueue.java:615)
    at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$7(IdeEventQueue.java:434)
    at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:838)
    at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:480)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92)
Caused by: java.lang.ClassCastException: class java.lang.Boolean cannot be cast to class java.lang.String (java.lang.Boolean and java.lang.String are in module java.base of loader 'bootstrap')
    at de.marhali.easyi18n.io.parser.yaml.YamlMapper.read(YamlMapper.java:17)
    at de.marhali.easyi18n.io.parser.yaml.YamlMapper.read(YamlMapper.java:23)
    at de.marhali.easyi18n.io.parser.yaml.YamlMapper.read(YamlMapper.java:23)
    at de.marhali.easyi18n.io.parser.yaml.YamlParserStrategy.read(YamlParserStrategy.java:59)
    at de.marhali.easyi18n.io.IOHandler.read(IOHandler.java:79)
    ... 36 more
xurei commented 1 year ago

I had the same issue. You can work around this by putting these texts between quotes:

enum:
  bool:
    yes: 'yes'
    no: 'no'
    on: 'on'
    off: 'off'
levalup commented 1 year ago

I had the same issue. You can work around this by putting these texts between quotes:

enum:
  bool:
    yes: 'yes'
    no: 'no'
    on: 'on'
    off: 'off'

Thanks. I tried this before, but it does not solve the problem I encountered very well. The fundamental problem is that the parser will also parse the key values (yes or no) of the dictionary into booleans, so it needs to be completely rewritten to achieve the expected effect.

enum:
  bool:
    'yes': 'yes'
    'no': 'no'
    'on': 'on'
    'off': 'off'

I don't think it's appropriate to trade key values(such as yes/no) into boolean, at least it should be able to prompt the user instead of crashing directly.

At least it should not crash, and then remind users that special strings should be enclosed in single quotation marks(').