Using a/an on an I18n message - ruby-on-rails

I have the following error message on my en.yml file:
invalid_transition: "Cannot %{action} a %{state} timesheet"
Problem is that sometimes the state can be approved, other times it can be rejected.
With that, the error can end up being mispelled like "Cannot submit a approved timesheet", instead of "an approved timesheet".
Does Rails provide this flexibility in I18n?

The most simple answer to your question, I think, would be to pass in the entire state with the correct indefinite article together.
There's a question that looks at how to prepend "a" or "an" depending on a given word. A short answer is that there's a gem indefinite_article that does it.
Your translation then becomes:
invalid_transition: "Cannot %{action} %{state_with_article} timesheet"
Then call the I18n.t and pass in "a rejected" or "an approved" as a variable to interpolate.
However, if you want to get your hands a bit dirtier you may be able to use the i18n-inflector gem and it's companion i18n-inflector-rails gem. For many languages the choice is more complicated than in English because of different genders and tenses affecting the choice of indefinite article. (Disclaimer: I've not used either of those gems but they look like they would help you solve the problem).

Related

Ruby net::imap adding color categorys to emails

I am reading in a lot of emails every day using net::imap
https://ruby-doc.org/stdlib-2.5.1/libdoc/net/imap/rdoc/Net/IMAP.html
I cannot seem to find a way to add a colored category to a message.
For example
imap.search(["ON","26-APR-2021"]).each do |message_id|
# my code...
# at the end of the code
message_id.AddCatagory(blue)...
end
The method name would be add_category in well-written ruby. But that doesn't exist, because colours aren't a concept in IMAP. Flags do exist, and I know some clients use colours to represent flags... so the code you're probably looking for is something along the lines of
imap.uid_store(uids, "+flags", [:Blue])
You have to define Blue, of course. Or Important, Flagged or something. Flagged is used by many clients for vaguely important messages.

How do I fix: ArgumentError: invalid byte sequence in UTF-8?

I am getting this type of error in the logs :
Parameters: {"id"=>"4", "step"=>{"documents_attributes"=>{"0"=>
{"file"=>"\x89PNG\r\n\u001A\n\u0000\u0000\u0000\rIHDR\u0000\..."}}}}
def update
#step = Step.find_by(id: params[:id])
if #step.update(steps_params)
render :json => #step
else
render :json => { :responseStatus => 402,
:responseMessage => #step.errors.full_messages.first}
end
end
During update, it rollbacks without giving any error (not execute else condition)
ArgumentError (invalid byte sequence in UTF-8):
(0.2ms) ROLLBACK
How can I fix or handle this type of request?
Your question is how to handle this type of request or error. So here is my suggestion of a general strategy.
First, do your homework. You could easily find this past question, for example. If you have tried the way already but found it did not work, you should have described what you did and what did not work in your question.
Now, I am assuming you can reproduce the case or at least you can expect you will encounter the same problem in near future (or you can wait till then) so you will have a more chance to pin down the problem next time. If you know what parameters caused the error, I guess you can reproduce the case in your development environment. However, if not, it is more tricky to pin down — it heavily depends how much information about the error and input you have and what development environment you can use, and my answer does not cover the case.
The first objective should be to pin down which command (method) exactly in your code caused an error. Did it happen just inside Rails or did your DB raise an error?
In your specific case, did it occur at Step.find_by or #step.update or else? What is steps_params? It seems like a method you have defined. Are you sure steps_params is working as expected? (You may be sure, but we don't know…)
A convenient way to find it out is simply to insert logger.debug (or logger.error) etc before and after each sentence. In doing it, it is recommended to split a sentence into smaller units in some cases. For example, steps_params and update() should be separated, such as (in the simplest case),
logger.debug 'Before steps_params'
res_steps_params = steps_params
logger.debug 'Before update'
res_update = #step.update(res_steps_params)
logger.debug 'Before if'
if res_update
# ……
Obviously you can (and perhaps should) log more detailed information, such as, res_steps_params.inspect, and you may also enclose a part with a begin-rescue clause so that you can get the detailed infromation about the exception and log it. Also, I can recommend to split update into 2 parts – substitutions and save – to find out exactly what action and parameter cause a problem.
Once you have worked out which of DB or Rails or something before (like HTTP-server or Client-browser) is to blame and which parameter causes a problem, then you can proceed to the next stage. The error message suggests it is a character-encoding issue. Is the character encoding of a string invalid (as a UTF-8), or wrongly recognised by Rails (which might be not a fault of Rails but of the client), or not recognised correctly by the DB?
Wherever the problem lies, it is usually (though not always!) possible to fix or circumvent character-encoding problems with Ruby (Rails). The Ruby methods of String#encode, String#encoding, and String#force_encoding would be useful to diagnose and perhaps fix the problem.
As an added note, it can be useful, if possible in your environment, to browse the logfile of your DB (PostgreSQL?) to find out which query passed from Rails to the DB caused a problem (if a query was indeed passed to them!). Alternatively, Rails Gem SQL Query Tracker might be handy to know what queries your Rails app create (though I have never used it and so can't tell much.)
At the end of the day, when a code misbehaves mysteriously, I am afraid only the sure way to solve is to narrow down the problematic clause or parameter step by step. Good luck!

Rails: i18n parameters that are also translated

I'm having difficulty finding the answer for my question, but it may just be that I have no idea how to phrase it. In svenfuchs's yml files in his rails-i18n repo, he has this listed under error:
format: #{attribute}#{message}
and below that he specifies possible error messages. It's really nifty, as it automatically translated error messages for me.
I'd like to use this format to translate headers and buttons. In Japanese, we'd say "FAQ Create" while in English we'd say "Create FAQ", so I can't just print out those translations and I'd like to not have to make each button's translation myself (a.k.a. create_faq: FAQを作る).
So far I've got in my view: t('button.format'), :attribute => "faq", :message => "create"
ja.yml:
model:
faq: FAQ
button:
format: #{attribute}#{message}
messages:
create: を作る
But that just prints out faqcreate for Japanese. What I'm trying to do is access the translations of model.faq and button.messages.create to pass as the parameters. Anybody know how?
p.s. messages: was also plural in the working errors message.
I'm sorry, I'm so stupid, I keep answering my questions right after I finally decided to ask for help;;; for anybody interested, just pass in another t(' '), so:
t('button.format', :attribute t('model.faq'), :message t('button.messages.create'))

rails i18n adjectives

I'm currently stuck with a small but not so uncommon problem in rails i18n ( hopefully I just haven't used the wrong search terms...)
In a standard rails crud app, you often have models like "contract", "group" etc..
So far, if you want a button for "new group" oder "new contract", this is simple in the english language, since it's basically always something like "new" + model_name.
Unfortunately, languages like german are not so computer-friendly :)
"new contract" translates to "neuer vertrag" while "new group" translates to "neue gruppe" (note the adjective change).
So, no problem with pluralisation this time but with adjective changes.
Is there any rails i18n support for such cases?
Don't want to use ugly i18n concatenation :)
thanks a lot!
just to understand your question correctly, you don't want to translate 'new' to german?
What is wrong with:
en:
new_contract: New contract
new_group: New group
de:
new_contract: Neuer Vertrag
new_group: Neue Gruppe
This is the standard way to do it and I don't see any advantage of DRYing up the 'new'. You remove something from the context there. Btw. you have this problem in a lot of languages. It is not possible to translate an adjective just once and then reuse, since it belongs to another word (cannot stand in its own context).
I would definitely go with the approach above.

Overriding Rails Error (Validation) Messages from Gems/Plugins

Is there a generally accepted way of overriding error (validation) messages from a gem/plugin in rails?
For example, I'm using the ActiveMerchant gem, and if someone puts in an American Express credit card number, but selects 'MasterCard', I get a not-very-descriptive "Type is not the correct card type" error.
I can easily get around this by doing something like this:
def validate_card
unless credit_card.valid?
credit_card.errors.full_messages.each do |message|
if message =~ /is not the correct card type/i
errors.add_to_base "This credit card number is invalid.
Please ensure that you selected the correct type."
else
errors.add_to_base message
end
end
end
end
but this technique quickly becomes unmaintainable and is clearly (at least in my opinion) far from 'best-practices'.
Similarly, I could unpack the ActiveMerchant gem and hack it up to put in my own custom error messages, but that also seems unmaintainable as it would require the same hacks to added into future, unpacked, versions of ActiveMerchant.
In all honesty, you're best bet is to either rewrite parts of the gem/plugin to suit your needs. Unfortunately if you decide to update the gem/plugin at any time you will lose your changes.
However, Ruby is a dynamic language, so classes can be reopened, and you can override methods of any module/class from any file. Through the magic of open source, I've tracked down the module/class/method you'd need to meddle with to achieve your goal.
Put the following in a file and ensure it gets loaded after ActiveMerchant (how to load it is dependent on whether you're using the plugin or the gem)
module ActiveMerchant
module Billing
class CreditCard
private
def validate_card_number #:nodoc:
errors.add_to_base "This credit card number is invalid. \n" +
"Please ensure that you selected the correct type." unless
CreditCard.valid_number?(number)
end
end
end
end
N.B.: This method relies on ActiveMerchant internals, which is generally a bad idea. But I see it as the lesser of two evils to maintaing your own version of ActiveMerchant. Should you update the gem/plugin and something the above code relies on has changed, it could break in odd ways.

Resources