[yast-devel] Idea: Dynamic Folding of Translated Texts
Hi, I've just got an idea and wanted to know your opinion. This came to my mind when evaluating https://trello.com/c/UKTnEvME (which might not be accessible for some of you, thus explaining below). # The problem We often inform users in dialogs (e.g. warning pop-up, labels) about some current situation which contains a generated text based on, for instance, lists of disks or network interfaces. In many cases, the length of these lists/strings is unknown when we write the text in our code. Moreover, translations can change it quite a lot. Depending on the selected UI type, we might or might not fit. # Example ---------------------------------------------------------------------- You are trying to create subvolume {new_subvolume_name} which would be shadowed by subvolume {old_subvolume_name} and thus might not produce the desired effect. Continue despite the fact that we have warned you? ---------------------------------------------------------------------- In bad the example above, subvolumes can be short, but they can be also very long. Some languages will use very long translation, some other ones a shorter one. # Solution Basically something like `fold`, but implemented in Ruby without calling shell. Maybe in Yast::String, maybe even as a Yast built-in (fold, wrap, wrap_at). We could, for instance, get inspired here https://www.safaribooksonline.com/library/view/ruby-cookbook/0596523696/ch01... but I'd like to see some safe defaults depending on the selected UI or even UI capabilities such as number of columns in ncurses. What are your thoughts about it? If you tell me that we already have it, the better :) We just should start using it. Thanks Lukas -- Lukas Ocilka, Systems Management (Yast) Team Leader SLE Department, SUSE Linux https://en.wikipedia.org/wiki/Scout_Promise#Czech_Republic http://www.scouting.org/Visitor/WhyScouting/ServingOthers.aspx -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org To contact the owner, e-mail: yast-devel+owner@opensuse.org
Dne 12.5.2016 v 08:49 Lukas Ocilka napsal(a):
# Example
---------------------------------------------------------------------- You are trying to create subvolume {new_subvolume_name} which would be shadowed by subvolume {old_subvolume_name} and thus might not produce the desired effect. Continue despite the fact that we have warned you? ----------------------------------------------------------------------
In bad the example above, subvolumes can be short, but they can be also very long. Some languages will use very long translation, some other ones a shorter one.
My workaround is to put the variable text on a separate line to avoid text overflow, e.g [1]: # %s is an extension name, e.g. "SUSE Linux Enterprise Software Development Kit" Yast::Report.Error(_("Downloading the license for\n%s\nfailed.") % addon.label) This workaround makes sense when the text is usually long. When the variable text is short then it looks ugly.
# Solution
Basically something like `fold`, but implemented in Ruby without calling shell. Maybe in Yast::String, maybe even as a Yast built-in (fold, wrap, wrap_at).
Actually this should be implemented on the UI level as only the UI can know how much space there is and how long text can fit there. Moreover in Qt we use proportional font, that means "iiiiiiiiiiiiiiiiii" might fit while "mmmmmmmmmmmmmmmmmm" might not even though both have the exactly same number of characters. And I guess with non-Latin alphabets (Arabic, Japanese, ...) it would break very easily... The implementation at the YaST logic layer would not work well in many cases, IMHO that's a wrong place for this functionality. # Solution 2 My suggestion would be to add Opt(:wrap) option to the Label() widget which would enable the line wrapping. The text would be a single line and the UI would take care of breaking the lines at the appropriate places. Example: Label(Opt(:wrap), "verlongtext" * 42) What do you think about it? [1] https://github.com/yast/yast-registration/blob/master/src/lib/registration/u... -- Ladislav Slezák Appliance department / YaST Developer Lihovarská 1060/12 190 00 Prague 9 / Czech Republic tel: +420 284 028 960 lslezak@suse.com SUSE -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org To contact the owner, e-mail: yast-devel+owner@opensuse.org
On 05/12/2016 08:49 AM, Ladislav Slezak wrote:
Dne 12.5.2016 v 08:49 Lukas Ocilka napsal(a):
# Example
---------------------------------------------------------------------- You are trying to create subvolume {new_subvolume_name} which would be shadowed by subvolume {old_subvolume_name} and thus might not produce the desired effect. Continue despite the fact that we have warned you? ----------------------------------------------------------------------
In bad the example above, subvolumes can be short, but they can be also very long. Some languages will use very long translation, some other ones a shorter one.
My workaround is to put the variable text on a separate line to avoid text overflow, e.g [1]:
# %s is an extension name, e.g. "SUSE Linux Enterprise Software Development Kit" Yast::Report.Error(_("Downloading the license for\n%s\nfailed.") % addon.label)
In this case i used same workaround, but i didn't take care of the first line size and also we have the problems about unkown number of interfaces per physical port id. The code is something like that: + Popup.YesNoHeadline( + Label.WarningMsg, + _("The interfaces selected for bonding map to same physical port \n" \ + "and bonding them may not have the desire result.\n\n%s\n" \ + "Really continue?\n") % message + ) And the message was something like: + message = "" + + physical_port_ids.each do |port, devs| + message << "PhysicalPortID (#{port}): devs.join(', ')\n" + end So after the Lukas suggestion i added: + message = "" + + physical_port_ids.each do |port, devs| + message << "PhysicalPortID (#{port}):\n" + message << "#{devices_to_s(devs)}\n" + end + def devices_to_s(devices, wrap=78) + lines = [] + message_line = "" + devices.map do |d| + if !message_line.empty? && "#{message_line}#{d}".size > wrap + lines << message_line + message_line = "" + end + + message_line << ", " if !message_line.empty? + message_line << d + end + lines << message_line if !message_line.empty? + + lines.join("\n") + end The devices_to_s is almost the same method as the one referenced in kobliha link. And now i will try to take care of number of lines as you could have many (physical_ports_ids). You can see the results here: https://trello-attachments.s3.amazonaws.com/56c43586c0fb23f985367990/735x552... Apart of the Rails wrap method, there is some gem https://github.com/pazdera/word_wrap that implements it.
This workaround makes sense when the text is usually long. When the variable text is short then it looks ugly.
# Solution
Basically something like `fold`, but implemented in Ruby without calling shell. Maybe in Yast::String, maybe even as a Yast built-in (fold, wrap, wrap_at).
Actually this should be implemented on the UI level as only the UI can know how much space there is and how long text can fit there.
Moreover in Qt we use proportional font, that means "iiiiiiiiiiiiiiiiii" might fit while "mmmmmmmmmmmmmmmmmm" might not even though both have the exactly same number of characters. And I guess with non-Latin alphabets (Arabic, Japanese, ...) it would break very easily...
The implementation at the YaST logic layer would not work well in many cases, IMHO that's a wrong place for this functionality.
# Solution 2
My suggestion would be to add Opt(:wrap) option to the Label() widget which would enable the line wrapping. The text would be a single line and the UI would take care of breaking the lines at the appropriate places. Example:
Label(Opt(:wrap), "verlongtext" * 42)
What do you think about it?
[1] https://github.com/yast/yast-registration/blob/master/src/lib/registration/u...
--
Ladislav Slezák Appliance department / YaST Developer Lihovarská 1060/12 190 00 Prague 9 / Czech Republic tel: +420 284 028 960 lslezak@suse.com SUSE
-- Knut Alejandro Anderssen González YaST Team at SUSE Linux GmbH -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org To contact the owner, e-mail: yast-devel+owner@opensuse.org
Have we got some decision about this?, to know if let it in the network module by now just for the current problem or move it to a more generic class trying to DRY. On 05/12/2016 12:48 PM, Knut Alejandro Anderssen González wrote:
On 05/12/2016 08:49 AM, Ladislav Slezak wrote:
Dne 12.5.2016 v 08:49 Lukas Ocilka napsal(a):
# Example
---------------------------------------------------------------------- You are trying to create subvolume {new_subvolume_name} which would be shadowed by subvolume {old_subvolume_name} and thus might not produce the desired effect. Continue despite the fact that we have warned you? ----------------------------------------------------------------------
In bad the example above, subvolumes can be short, but they can be also very long. Some languages will use very long translation, some other ones a shorter one.
My workaround is to put the variable text on a separate line to avoid text overflow, e.g [1]:
# %s is an extension name, e.g. "SUSE Linux Enterprise Software Development Kit" Yast::Report.Error(_("Downloading the license for\n%s\nfailed.") % addon.label)
In this case i used same workaround, but i didn't take care of the first line size and also we have the problems about unkown number of interfaces per physical port id.
The code is something like that: + Popup.YesNoHeadline( + Label.WarningMsg, + _("The interfaces selected for bonding map to same physical port \n" \ + "and bonding them may not have the desire result.\n\n%s\n" \ + "Really continue?\n") % message + )
And the message was something like:
+ message = "" + + physical_port_ids.each do |port, devs| + message << "PhysicalPortID (#{port}): devs.join(', ')\n" + end
So after the Lukas suggestion i added:
+ message = "" + + physical_port_ids.each do |port, devs| + message << "PhysicalPortID (#{port}):\n" + message << "#{devices_to_s(devs)}\n" + end
+ def devices_to_s(devices, wrap=78) + lines = [] + message_line = "" + devices.map do |d| + if !message_line.empty? && "#{message_line}#{d}".size > wrap + lines << message_line + message_line = "" + end + + message_line << ", " if !message_line.empty? + message_line << d + end + lines << message_line if !message_line.empty? + + lines.join("\n") + end
The devices_to_s is almost the same method as the one referenced in kobliha link.
And now i will try to take care of number of lines as you could have many (physical_ports_ids).
You can see the results here:
https://trello-attachments.s3.amazonaws.com/56c43586c0fb23f985367990/735x552...
Apart of the Rails wrap method, there is some gem https://github.com/pazdera/word_wrap that implements it.
This workaround makes sense when the text is usually long. When the variable text is short then it looks ugly.
# Solution
Basically something like `fold`, but implemented in Ruby without calling shell. Maybe in Yast::String, maybe even as a Yast built-in (fold, wrap, wrap_at).
Actually this should be implemented on the UI level as only the UI can know how much space there is and how long text can fit there.
Moreover in Qt we use proportional font, that means "iiiiiiiiiiiiiiiiii" might fit while "mmmmmmmmmmmmmmmmmm" might not even though both have the exactly same number of characters. And I guess with non-Latin alphabets (Arabic, Japanese, ...) it would break very easily...
The implementation at the YaST logic layer would not work well in many cases, IMHO that's a wrong place for this functionality.
# Solution 2
My suggestion would be to add Opt(:wrap) option to the Label() widget which would enable the line wrapping. The text would be a single line and the UI would take care of breaking the lines at the appropriate places. Example:
Label(Opt(:wrap), "verlongtext" * 42)
What do you think about it?
[1] https://github.com/yast/yast-registration/blob/master/src/lib/registration/u...
--
Ladislav Slezák Appliance department / YaST Developer Lihovarská 1060/12 190 00 Prague 9 / Czech Republic tel: +420 284 028 960 lslezak@suse.com SUSE
-- Knut Alejandro Anderssen González YaST Team at SUSE Linux GmbH -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org To contact the owner, e-mail: yast-devel+owner@opensuse.org
On 13.5.2016 10:21, Knut Alejandro Anderssen González wrote:
Have we got some decision about this?, to know if let it in the network module by now just for the current problem or move it to a more generic class trying to DRY.
Form my POV, I'd like to see it at some "generic" place, that's the reason why I started this discussion. On the other hand 1. It's not necessary to fulfill the PBI 2. Input from others about the actual implementation is needed When introducing new API, the team should be aware of it and it should be good enough for the future. So, let's wait for others to say a word about it. Thx Lukas -- Lukas Ocilka, Systems Management (Yast) Team Leader SLE Department, SUSE Linux https://en.wikipedia.org/wiki/Scout_Promise#Czech_Republic http://www.scouting.org/Visitor/WhyScouting/ServingOthers.aspx -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org To contact the owner, e-mail: yast-devel+owner@opensuse.org
On Thu, May 12, 2016 at 08:49:03AM +0200, Lukas Ocilka wrote:
# The problem
We often inform users in dialogs (e.g. warning pop-up, labels) about some current situation which contains a generated text based on, for instance, lists of disks or network interfaces. In many cases, the length of these lists/strings is unknown when we write the text in our code. Moreover, translations can change it quite a lot. Depending on the selected UI type, we might or might not fit.
# Solution
Basically something like `fold`, but implemented in Ruby without calling shell. Maybe in Yast::String, maybe even as a Yast built-in (fold, wrap, wrap_at).
What are your thoughts about it? If you tell me that we already have it, the better :) We just should start using it.
Yes, we should have something like that. I even created a feature request many years ago but it was rejected several times. But the implementation should be in the UI since only that knows the font metric. Also when resizing dialogs the Ruby code is not rerun. And we have to remember that there are languages not using spaces for line-wrap, e.g. Japanese. Maybe other languages also need special handling. ciao Arvin -- Arvin Schnell, <aschnell@suse.com> Senior Software Engineer, Research & Development SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg) Maxfeldstraße 5 90409 Nürnberg Germany -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org To contact the owner, e-mail: yast-devel+owner@opensuse.org
On Thu, May 12, 2016 at 08:49:03AM +0200, Lukas Ocilka wrote:
# The problem
We often inform users in dialogs (e.g. warning pop-up, labels) about some current situation which contains a generated text based on, for instance, lists of disks or network interfaces. In many cases, the length of these lists/strings is unknown when we write the text in our code. Moreover, translations can change it quite a lot. Depending on the selected UI type, we might or might not fit.
For reference, Rails has word_wrap: http://apidock.com/rails/ActionView/Helpers/TextHelper/word_wrap word_wrap(text, options = {}) public Wraps the text into lines no longer than line_width width. This method breaks on the first whitespace character that does not exceed line_width (which is 80 by default). word_wrap('Once upon a time') # => Once upon a time word_wrap('Once upon a time, in a kingdom called Far Far Away, a king fell ill, and finding a successor to the throne turned out to be more trouble than anyone could have imagined...') # => Once upon a time, in a kingdom called Far Far Away, a king fell # ill, and finding\na successor to the throne turned out to be more # trouble than anyone could have\nimagined... word_wrap('Once upon a time', line_width: 8) # => Once\nupon a\ntime word_wrap('Once upon a time', line_width: 1) # => Once\nupon\na\ntime -- Martin Vidner, YaST Team http://en.opensuse.org/User:Mvidner Kuracke oddeleni v restauraci je jako fekalni oddeleni v bazenu
participants (5)
-
Arvin Schnell
-
Knut Alejandro Anderssen González
-
Ladislav Slezak
-
Lukas Ocilka
-
Martin Vidner