Muchas veces, al generar mensajes para mostrar al usuario, el mensaje contendrá una serie de algo sobre lo que quiero informar al cliente.
Daré un ejemplo: el cliente ha seleccionado varios elementos del 1 en adelante y ha hecho clic en eliminar. Ahora quiero enviar un mensaje de confirmación al cliente, y quiero mencionar la cantidad de elementos que ha seleccionado para minimizar la posibilidad de que cometa un error al seleccionar un montón de elementos y hacer clic en eliminar cuando solo quiere eliminar uno de ellos.
Una forma es hacer que el mensaje genérico sea así:
int noofitemsselected = SomeFunction();
string message = "You have selected " + noofitemsselected + " item(s). Are you sure you want to delete it/them?";
El "problema" aquí es el caso donde noofitemselected
es 1, y tenemos que escribir item y él en lugar de items y ellos .
Mi solución normal será algo como esto
int noofitemsselected = SomeFunction();
string message = "You have selected " + noofitemsselected + " " + (noofitemsselected==1?"item" : "items") + ". Are you sure you want to delete " + (noofitemsselected==1?"it" : "them") + "?";
Esto se vuelve bastante largo y bastante desagradable muy rápido si hay muchas referencias a la pluralidad de números dentro del código, y el mensaje real se vuelve difícil de leer.
Entonces mi pregunta es simple. ¿Existen mejores formas de generar mensajes como este?
EDITAR
Veo que muchas personas se han quedado muy colgadas en el caso de que mencioné que el mensaje debería mostrarse dentro de un cuadro de mensaje, y simplemente dio una respuesta de cómo evitar usar el cuadro de mensaje, y eso está muy bien. .
Pero recuerde que el problema de la pluralización también se aplica a textos en otros lugares del programa además de los cuadros de mensajes. Por ejemplo, una etiqueta junto a una cuadrícula que muestre el número de líneas seleccionadas en la cuadrícula tendrá el mismo problema con respecto a la pluralización.
Entonces, esto básicamente se aplica a la mayoría del texto que se genera de alguna manera desde los programas, y luego la solución no es tan simple como simplemente cambiar el programa para que ya no genere texto :)
fuente
Respuestas:
Si alguna vez existe la posibilidad, por pequeña que sea, de que esta aplicación deba traducirse a otros idiomas, ambos están equivocados. La forma correcta de hacer esto es:
Esto se debe a que los diferentes idiomas manejan la pluralidad de manera diferente. Algunos, como el malayo, ni siquiera tienen plurales sintácticos, por lo que las cadenas suelen ser idénticas. La separación de las dos cadenas facilita la compatibilidad con otros idiomas más adelante.
De lo contrario, si esta aplicación está destinada a ser consumida por el público en general y se supone que es fácil de usar, entonces es preferible el segundo método. Lo siento, pero realmente no conozco una forma más corta de hacer esto.
Si esta aplicación está destinada a ser consumida solo internamente por su empresa, haga el atajo
"item(s)"
. Realmente no tiene que impresionar a nadie al escribir código enterprisy. Pero desaconsejaría hacer esto para aplicaciones de consumo público porque da la impresión de que el programador es vago y, por lo tanto, reduce su opinión sobre la calidad de la aplicación. Créame, pequeñas cosas como esta importan.fuente
noofitemsselected
en este ejemplo para la primera opción; ya que sabe que es 1.Puede evitar toda esta pluralidad desordenada simplemente eliminando los elementos sin ningún mensaje y brindando al usuario una función Deshacer realmente buena. Los usuarios nunca leen nada . De todos modos, debería crear una buena función Deshacer como parte de su programa.
De hecho, obtiene 2 beneficios cuando crea una función completa de Deshacer. El primer beneficio facilita la vida del usuario al permitirle revertir los errores y minimizar la lectura. El segundo beneficio es que su aplicación refleja la vida real al permitir la reversión del flujo de trabajo no trivial (no solo errores).
Una vez escribí una aplicación sin usar un solo diálogo o mensaje de confirmación. Tomó un pensamiento serio y fue significativamente más difícil de implementar que usar mensajes de tipo confirmación. Pero el resultado final fue bastante agradable de usar según sus usuarios finales.
fuente
¿Qué tal solo:
De esa manera, elimina las dificultades del acuerdo numérico y termina con un mensaje de error aún más corto y más directo para el usuario como beneficio adicional. Todos sabemos que los usuarios no leen los mensajes de error de todos modos . Cuanto más cortos sean, más probable es que al menos echen un vistazo al texto.
O, armado con este conocimiento de que los usuarios no leen los mensajes de error, podría abordar esto de una manera diferente. Omita el mensaje de confirmación por completo y solo proporcione una función de deshacer que Just Works, independientemente de lo que se eliminó. La mayoría de los usuarios ya están acostumbrados a deshacer una operación cuando se dan cuenta de que no era lo que querían y es probable que encuentren este comportamiento más natural que tener que lidiar con otra ventana emergente molesta.
fuente
¿Qué pasa con lo que Java ha tenido durante años: java.text.MessageFormat y ChoiceFormat? Consulte http://download.oracle.com/javase/1.4.2/docs/api/java/text/MessageFormat.html para obtener más información.
En tu caso quieres algo algo más sencillo:
La ventaja de este enfoque es que funciona bien con los paquetes i18n y puede proporcionar traducciones correctamente para idiomas (como el japonés) que no tienen concepto de palabras en plural o singular.
fuente
Yo optaría por no codificar el mensaje, sino por proporcionar dos mensajes en un archivo de recursos separado. Me gusta
y luego alimentarlos en String.Format like
Creo que este enfoque es más fácil de localizar y mantener. Todos los mensajes de la interfaz de usuario estarían en una única ubicación.
fuente
Puede eludir el problema por completo redactando el mensaje de manera diferente.
fuente
Lo primero que sugeriría es: use
string.Format
. Eso te permite hacer algo como esto:Además, en las aplicaciones de WPF, he visto sistemas en los que una cadena de recursos estaría delimitada por tuberías para tener dos mensajes: un mensaje en singular y uno en plural (o un mensaje cero / único / muchos, incluso). Luego, se podría usar un convertidor personalizado para analizar este recurso y usar la cadena relevante (formateada), por lo que su Xaml es algo como esto:
fuente
Para inglés, muchas respuestas arriba. Para otros idiomas es más difícil, ya que los plurales dependen del género del sustantivo y de la terminación de la palabra. Algunos ejemplos en francés:
Masculino regular:
Regular femenino
Masculino irregular (termina con 's')
El mismo problema existe en la mayoría de las lenguas latinas y se agrava en alemán o ruso, donde hay 3 géneros (masculino, femenino y neutro).
Deberá tener cuidado si su objetivo es manejar algo más que inglés.
fuente
Para poder tener mensajes pluralizados que se puedan localizar correctamente, mi opinión es que sería prudente crear primero una capa de indirección entre el número y un mensaje.
Por ejemplo, use una constante de algún tipo para especificar qué mensaje desea mostrar. Obtenga el mensaje usando alguna función que ocultará los detalles de implementación.
A continuación, cree un diccionario que contenga los posibles mensajes y variaciones, y haga que las variaciones sepan cuándo deben usarse.
Ahora simplemente puede encontrar la clave que corresponde a
quantity
e interpolar el valor dequantity
con ese mensaje.Este ejemplo simplificado e ingenuo, pero realmente no veo ninguna otra forma sensata de hacer esto y poder proporcionar un buen soporte para L10N e I18N.
fuente
Tendrá que traducir la función a continuación de VBA a C #, pero su uso cambiaría a:
Tengo una función VBA que utilizo en MS Access para hacer exactamente lo que estás hablando. Sé que me cortarán en pedazos por publicar VBA, pero aquí va de todos modos. El algoritmo debería ser evidente a partir de los comentarios:
El uso se cortó un poco en los comentarios del código anteriores, así que lo repetiré aquí:
Sí, esta solución ignora los idiomas que no son el inglés. Si eso importa depende de sus requisitos.
fuente
Puede generar el plural automáticamente, consulte, por ejemplo. generador plural .
Para ver las reglas de generación de plural, consulte wikipedia
fuente
¿Qué tal una forma más genérica? Evite la pluralización en la segunda oración:
Descubrí que hacerlo de esta manera coloca el número al final de la línea, lo cual es realmente fácil de detectar. Esta solución funcionaría con la misma lógica en cualquier idioma.
fuente
Number
(estaba respondiendo mientras mecía a mi bebé para dormir).Mi enfoque general es escribir una "función única / plural", como esta:
Luego, en el cuerpo del mensaje llamo a esta función:
Esto no es mucho mejor, pero al menos, (a) pone la decisión en una función y así despeja un poco el código, y (b) es lo suficientemente flexible para manejar plurales irregulares. es decir, es bastante fácil decir sustantivo (n, "niño", "niños") y cosas por el estilo.
Por supuesto, esto solo funciona para inglés, pero el concepto es fácilmente extensible a idiomas con terminaciones más complejas.
Se me ocurre que podría hacer que el último parámetro sea opcional para el caso fácil:
fuente
Internacionalización
Supongo que desea soporte para la internacionalización, en cuyo caso diferentes idiomas tienen diferentes patrones de plurales (por ejemplo, una forma plural especial para 2 de algo, o idiomas más complicados como el polaco), y no puede confiar en aplicar un patrón simple a su cadena arreglarlo.
Puede utilizar la
ngettext
función GNU Gettext y proporcionar dos mensajes en inglés en su código fuente. Gettext proporcionará la infraestructura para elegir entre otros (potencialmente más) mensajes cuando se traduzca a otros idiomas. Consulte http://www.gnu.org/software/hello/manual/gettext/Plural-forms.html para obtener una descripción completa del soporte plural de GNU gettext.GNU Gettext está bajo la LGPL.
ngettext
se nombraGettextResourceManager.GetPluralString
en el puerto C # de Gettext.(Si no necesita soporte de localización y no quiere usar Gettext de inmediato, escriba su propia función que haga esto para inglés y pase dos mensajes completos , de esa manera si necesita l10n más tarde, puede agregar reescribiendo una sola función).
fuente
¿Qué tal escribir una función como
.. y utilizarlo siempre que lo necesite?
fuente
Para el primer problema, me refiero a Pluralizar, puedes usar Inflector .
Y para el segundo, puede usar una extensión de representación de cadena con un nombre como ToPronounString.
fuente
Un miembro de nuestro equipo me planteó exactamente la misma pregunta ayer.
Desde que volvió a aparecer aquí en StackOverflow, pensé que el universo me estaba diciendo que tuviera una oportunidad para producir una solución decente.
Rápidamente armé algo y de ninguna manera es perfecto, sin embargo, podría ser útil o generar alguna discusión / desarrollo.
Este código se basa en la idea de que puede haber 3 mensajes. Uno para cero artículos, uno para un artículo y uno para más de un artículo que siguen la siguiente estructura:
singlePropertyName
singlePropertyName_Zero
singlePropertyName_Plural
He creado una clase interna para probar con el fin de imitar la clase de recursos. Todavía no he probado esto con un archivo de recursos real, así que aún no he visto el resultado completo.
Aquí está el código (actualmente he incluido algunos genéricos donde sé que podría haber especificado el tercer parámetro simplemente como un Tipo y también el segundo parámetro es una cadena, creo que hay una manera de combinar estos dos parámetros en algo mejor, pero yo ' Volveré a eso cuando tenga un momento libre.
Prueba de clase de recurso:
y mi método de ejecución rápida
fuente
singlePropertyName_All
que sea aún más obvio.Desde mi punto de vista, su primera solución es la más adecuada. Lo que digo es que, en caso de que necesite que la aplicación admita varios idiomas, la segunda opción puede ser laboriosa. Con el primer enfoque, es fácil localizar el texto sin mucho esfuerzo.
fuente
Podría optar por un mensaje más genérico como "¿Está seguro de que desea eliminar los elementos seleccionados?".
fuente
Depende de lo lindo que sea el mensaje que quieras tener. Del más fácil al más difícil:
Vuelva a escribir su mensaje de error para evitar la pluralización. No es tan agradable para tu usuario, pero más rápido.
Utilice un lenguaje más general, pero aún incluya los números.
Utilice un sistema de "pluralización" e inflector ala Rails, para que pueda decir
pluralize(5,'bunch')
y obtener5 bunches
. Rails tiene un buen patrón para esto.Para la internacionalización, debe mirar lo que ofrece Java. Eso admitirá una amplia variedad de idiomas, incluidos los que tienen diferentes formas de adjetivos con 2 o 3 elementos. La solución "s" está muy centrada en el inglés.
La opción que elija dependerá de los objetivos de su producto. - ndp
fuente
¿Por qué querría presentar un mensaje que los usuarios realmente puedan entender? Va en contra de los 40 años de historia de la programación. Nooooo, tenemos algo bueno, no lo estropees con mensajes comprensibles .
(j / k)
fuente
Hazlo como se hace en World of Warcraft:
fuente
Se vuelve un poco más corto con
fuente
Un enfoque que no he visto mencionado sería el uso de una etiqueta de sustitución / selección (por ejemplo, algo como "Estás a punto de aplastar {0} [? I ({0} = 1): / cactus / cacti /]". (en otras palabras, tenga una expresión similar a un formato que especifique la sustitución en función de si el argumento cero, tomado como un número entero, es igual a 1). He visto este tipo de etiquetas en los días anteriores a .net; no tengo conocimiento de ninguna estándar para ellos en .net, ni conozco la mejor manera de formatearlos.
fuente
Pensaría fuera de la caja por un minuto, todas las sugerencias aquí son hacer la pluralización (y preocuparse por más de 1 nivel de pluralización, género, etc.) o no usarlo en absoluto y proporcionar un buen deshacer.
Seguiría el camino no lingual y usaría colas visuales para eso. Por ejemplo, imagina una aplicación de Iphone que seleccionas elementos limpiando el dedo. antes de eliminarlos con el botón de eliminación maestro, "agitará" los elementos seleccionados y le mostrará un cuadro de interrogación titulado con los botones V (ok) o X (cancelar) ...
O, en el mundo 3D de Kinekt / Move / Wii - imagina seleccionar los archivos, mover tu mano al botón de borrar y que te digan que muevas tu mano sobre tu cabeza para confirmar (usando los mismos símbolos visuales que mencioné antes. de pedirle que elimine 3 archivos, le mostrará 3 archivos con una X roja medio transparente flotando y le dirá que haga algo para confirmar.
fuente