[gnome-software] Show the correct age classification information for different country-specific systems



commit dda530c618f0bcf8ff024d5f9075a1af31c98275
Author: Richard Hughes <richard hughsie com>
Date:   Wed Sep 21 21:36:18 2016 +0100

    Show the correct age classification information for different country-specific systems

 po/POTFILES.in          |    1 +
 src/Makefile.am         |    2 +
 src/gs-common.c         |  218 ------------------
 src/gs-common.h         |    3 -
 src/gs-content-rating.c |  569 +++++++++++++++++++++++++++++++++++++++++++++++
 src/gs-content-rating.h |   62 +++++
 src/gs-shell-details.c  |   29 ++-
 7 files changed, 658 insertions(+), 226 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 123211e..c385a7a 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -60,6 +60,7 @@ src/gs-update-monitor.c
 src/gs-upgrade-banner.c
 [type: gettext/glade]src/gs-upgrade-banner.ui
 src/gs-common.c
+src/gs-content-rating.c
 [type: gettext/glade]src/gs-menus.ui
 src/org.gnome.Software.desktop.in
 [type: gettext/glade]src/gs-popular-tile.ui
diff --git a/src/Makefile.am b/src/Makefile.am
index ef5a302..e0d5040 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -159,6 +159,8 @@ gnome_software_SOURCES =                            \
        gs-category-private.h                           \
        gs-common.c                                     \
        gs-common.h                                     \
+       gs-content-rating.c                             \
+       gs-content-rating.h                             \
        gs-debug.c                                      \
        gs-debug.h                                      \
        gs-app-addon-row.c                              \
diff --git a/src/gs-common.c b/src/gs-common.c
index 5e67945..c297a91 100644
--- a/src/gs-common.c
+++ b/src/gs-common.c
@@ -311,224 +311,6 @@ gs_image_set_from_pixbuf (GtkImage *image, const GdkPixbuf *pixbuf)
        gs_image_set_from_pixbuf_with_scale (image, pixbuf, scale);
 }
 
-const gchar *
-gs_utils_content_rating_kv_to_str (const gchar *id, AsContentRatingValue value)
-{
-       guint i;
-       struct {
-               const gchar             *id;
-               AsContentRatingValue     value;
-               const gchar             *desc;
-       } tab[] =  {
-       { "violence-cartoon",   AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No cartoon violence") },
-       { "violence-cartoon",   AS_CONTENT_RATING_VALUE_MILD,
-       /* TRANSLATORS: content rating description */
-       _("Cartoon characters in unsafe situations") },
-       { "violence-cartoon",   AS_CONTENT_RATING_VALUE_MODERATE,
-       /* TRANSLATORS: content rating description */
-       _("Cartoon characters in aggressive conflict") },
-       { "violence-cartoon",   AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Graphic violence involving cartoon characters") },
-       { "violence-fantasy",   AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No fantasy violence") },
-       { "violence-fantasy",   AS_CONTENT_RATING_VALUE_MILD,
-       /* TRANSLATORS: content rating description */
-       _("Characters in unsafe situations easily distinguishable from reality") },
-       { "violence-fantasy",   AS_CONTENT_RATING_VALUE_MODERATE,
-       /* TRANSLATORS: content rating description */
-       _("Characters in aggressive conflict easily distinguishable from reality") },
-       { "violence-fantasy",   AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Graphic violence easily distinguishable from reality") },
-       { "violence-realistic", AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No realistic violence") },
-       { "violence-realistic", AS_CONTENT_RATING_VALUE_MILD,
-       /* TRANSLATORS: content rating description */
-       _("Mildly realistic characters in unsafe situations") },
-       { "violence-realistic", AS_CONTENT_RATING_VALUE_MODERATE,
-       /* TRANSLATORS: content rating description */
-       _("Depictions of realistic characters in aggressive conflict") },
-       { "violence-realistic", AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Graphic violence involving realistic characters") },
-       { "violence-bloodshed", AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No bloodshed") },
-       { "violence-bloodshed", AS_CONTENT_RATING_VALUE_MILD,
-       /* TRANSLATORS: content rating description */
-       _("Unrealistic bloodshed") },
-       { "violence-bloodshed", AS_CONTENT_RATING_VALUE_MODERATE,
-       /* TRANSLATORS: content rating description */
-       _("Realistic bloodshed") },
-       { "violence-bloodshed", AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Depictions of bloodshed and the mutilation of body parts") },
-       { "violence-sexual",    AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No sexual violence") },
-       { "violence-sexual",    AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Rape or other violent sexual behavior") },
-       { "drugs-alcohol",      AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No references to alcohol") },
-       { "drugs-alcohol",      AS_CONTENT_RATING_VALUE_MILD,
-       /* TRANSLATORS: content rating description */
-       _("References to alcoholic beverages") },
-       { "drugs-alcohol",      AS_CONTENT_RATING_VALUE_MODERATE,
-       /* TRANSLATORS: content rating description */
-       _("Use of alcoholic beverages") },
-       { "drugs-narcotics",    AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No references to illicit drugs") },
-       { "drugs-narcotics",    AS_CONTENT_RATING_VALUE_MILD,
-       /* TRANSLATORS: content rating description */
-       _("References to illicit drugs") },
-       { "drugs-narcotics",    AS_CONTENT_RATING_VALUE_MODERATE,
-       /* TRANSLATORS: content rating description */
-       _("Use of illicit drugs") },
-       { "drugs-tobacco",      AS_CONTENT_RATING_VALUE_MILD,
-       /* TRANSLATORS: content rating description */
-       _("References to tobacco products") },
-       { "drugs-tobacco",      AS_CONTENT_RATING_VALUE_MODERATE,
-       /* TRANSLATORS: content rating description */
-       _("Use of tobacco products") },
-       { "sex-nudity",         AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No nudity of any sort") },
-       { "sex-nudity",         AS_CONTENT_RATING_VALUE_MILD,
-       /* TRANSLATORS: content rating description */
-       _("Brief artistic nudity") },
-       { "sex-nudity",         AS_CONTENT_RATING_VALUE_MODERATE,
-       /* TRANSLATORS: content rating description */
-       _("Prolonged nudity") },
-       { "sex-themes",         AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No references or depictions of sexual nature") },
-       { "sex-themes",         AS_CONTENT_RATING_VALUE_MILD,
-       /* TRANSLATORS: content rating description */
-       _("Provocative references or depictions") },
-       { "sex-themes",         AS_CONTENT_RATING_VALUE_MODERATE,
-       /* TRANSLATORS: content rating description */
-       _("Sexual references or depictions") },
-       { "sex-themes",         AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Graphic sexual behavior") },
-       { "language-profanity", AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No profanity of any kind") },
-       { "language-profanity", AS_CONTENT_RATING_VALUE_MILD,
-       /* TRANSLATORS: content rating description */
-       _("Mild or infrequent use of profanity") },
-       { "language-profanity", AS_CONTENT_RATING_VALUE_MODERATE,
-       /* TRANSLATORS: content rating description */
-       _("Moderate use of profanity") },
-       { "language-profanity", AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Strong or frequent use of profanity") },
-       { "language-humor",     AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No innappropriate humor") },
-       { "language-humor",     AS_CONTENT_RATING_VALUE_MILD,
-       /* TRANSLATORS: content rating description */
-       _("Slapstick humor") },
-       { "language-humor",     AS_CONTENT_RATING_VALUE_MODERATE,
-       /* TRANSLATORS: content rating description */
-       _("Vulgar or bathroom humor") },
-       { "language-humor",     AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Mature or sexual humor") },
-       { "language-discrimination", AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No discriminatory language of any kind") },
-       { "language-discrimination", AS_CONTENT_RATING_VALUE_MILD,
-       /* TRANSLATORS: content rating description */
-       _("Negativity towards a specific group of people") },
-       { "language-discrimination", AS_CONTENT_RATING_VALUE_MODERATE,
-       /* TRANSLATORS: content rating description */
-       _("Discrimination designed to cause emotional harm") },
-       { "language-discrimination", AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Explicit discrimination based on gender, sexuality, race or religion") },
-       { "money-advertising", AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No advertising of any kind") },
-       { "money-advertising", AS_CONTENT_RATING_VALUE_MILD,
-       /* TRANSLATORS: content rating description */
-       _("Product placement") },
-       { "money-advertising", AS_CONTENT_RATING_VALUE_MODERATE,
-       /* TRANSLATORS: content rating description */
-       _("Explicit references to specific brands or trademarked products") },
-       { "money-advertising", AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Players are encouraged to purchase specific real-world items") },
-       { "money-gambling",     AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No gambling of any kind") },
-       { "money-gambling",     AS_CONTENT_RATING_VALUE_MILD,
-       /* TRANSLATORS: content rating description */
-       _("Gambling on random events using tokens or credits") },
-       { "money-gambling",     AS_CONTENT_RATING_VALUE_MODERATE,
-       /* TRANSLATORS: content rating description */
-       _("Gambling using \"play\" money") },
-       { "money-gambling",     AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Gambling using real money") },
-       { "money-purchasing",   AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No ability to spend money") },
-       { "money-purchasing",   AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Ability to spend real money in-game") },
-       { "social-chat",        AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No way to chat with other players") },
-       { "social-chat",        AS_CONTENT_RATING_VALUE_MILD,
-       /* TRANSLATORS: content rating description */
-       _("Player-to-player game interactions without chat functionality") },
-       { "social-chat",        AS_CONTENT_RATING_VALUE_MODERATE,
-       /* TRANSLATORS: content rating description */
-       _("Player-to-player preset interactions without chat functionality") },
-       { "social-chat",        AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Uncontrolled chat functionality between players") },
-       { "social-audio",       AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No way to talk with other players") },
-       { "social-audio",       AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Uncontrolled audio or video chat functionality between players") },
-       { "social-contacts",    AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No sharing of social network usernames or email addresses") },
-       { "social-contacts",    AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Sharing social network usernames or email addresses") },
-       { "social-info",        AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No sharing of user information with 3rd parties") },
-       { "social-info",        AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Sharing user information with 3rd parties") },
-       { "social-location",    AS_CONTENT_RATING_VALUE_NONE,
-       /* TRANSLATORS: content rating description */
-       _("No sharing of physical location to other users") },
-       { "social-location",    AS_CONTENT_RATING_VALUE_INTENSE,
-       /* TRANSLATORS: content rating description */
-       _("Sharing physical location to other users") },
-       { NULL, 0, NULL } };
-       for (i = 0; tab[i].id != NULL; i++) {
-               if (g_strcmp0 (tab[i].id, id) == 0 && tab[i].value == value)
-                       return tab[i].desc;
-       }
-       return NULL;
-}
-
 gboolean
 gs_utils_is_current_desktop (const gchar *name)
 {
diff --git a/src/gs-common.h b/src/gs-common.h
index 631b9c9..0ee765c 100644
--- a/src/gs-common.h
+++ b/src/gs-common.h
@@ -48,9 +48,6 @@ void  gs_image_set_from_pixbuf_with_scale     (GtkImage               *image,
 void   gs_image_set_from_pixbuf                (GtkImage               *image,
                                                 const GdkPixbuf        *pixbuf);
 
-const gchar    *gs_utils_content_rating_kv_to_str (const gchar *id,
-                                               AsContentRatingValue value);
-
 const gchar    *gs_user_agent                  (void);
 gboolean        gs_utils_is_current_desktop    (const gchar    *name);
 void            gs_utils_widget_set_css_app    (GsApp          *app,
diff --git a/src/gs-content-rating.c b/src/gs-content-rating.c
new file mode 100644
index 0000000..d16e59f
--- /dev/null
+++ b/src/gs-content-rating.c
@@ -0,0 +1,569 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2015-2016 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include "gs-content-rating.h"
+
+const gchar *
+gs_content_rating_system_to_str (GsContentRatingSystem system)
+{
+       if (system == GS_CONTENT_RATING_SYSTEM_INCAA)
+               return "INCAA";
+       if (system == GS_CONTENT_RATING_SYSTEM_ACB)
+               return "ACB";
+       if (system == GS_CONTENT_RATING_SYSTEM_DJCTQ)
+               return "DJCTQ";
+       if (system == GS_CONTENT_RATING_SYSTEM_GSRR)
+               return "GSRR";
+       if (system == GS_CONTENT_RATING_SYSTEM_PEGI)
+               return "PEGI";
+       if (system == GS_CONTENT_RATING_SYSTEM_KAVI)
+               return "KAVI";
+       if (system == GS_CONTENT_RATING_SYSTEM_USK)
+               return "USK";
+       if (system == GS_CONTENT_RATING_SYSTEM_ESRA)
+               return "ESRA";
+       if (system == GS_CONTENT_RATING_SYSTEM_CERO)
+               return "CERO";
+       if (system == GS_CONTENT_RATING_SYSTEM_OFLCNZ)
+               return "OFLCNZ";
+       if (system == GS_CONTENT_RATING_SYSTEM_RUSSIA)
+               return "RUSSIA";
+       if (system == GS_CONTENT_RATING_SYSTEM_MDA)
+               return "MDA";
+       if (system == GS_CONTENT_RATING_SYSTEM_GRAC)
+               return "GRAC";
+       if (system == GS_CONTENT_RATING_SYSTEM_ESRB)
+               return "ESRB";
+       if (system == GS_CONTENT_RATING_SYSTEM_IARC)
+               return "IARC";
+       return NULL;
+}
+
+const gchar *
+gs_content_rating_key_value_to_str (const gchar *id, AsContentRatingValue value)
+{
+       guint i;
+       struct {
+               const gchar             *id;
+               AsContentRatingValue     value;
+               const gchar             *desc;
+       } tab[] =  {
+       { "violence-cartoon",   AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No cartoon violence") },
+       { "violence-cartoon",   AS_CONTENT_RATING_VALUE_MILD,
+       /* TRANSLATORS: content rating description */
+       _("Cartoon characters in unsafe situations") },
+       { "violence-cartoon",   AS_CONTENT_RATING_VALUE_MODERATE,
+       /* TRANSLATORS: content rating description */
+       _("Cartoon characters in aggressive conflict") },
+       { "violence-cartoon",   AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Graphic violence involving cartoon characters") },
+       { "violence-fantasy",   AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No fantasy violence") },
+       { "violence-fantasy",   AS_CONTENT_RATING_VALUE_MILD,
+       /* TRANSLATORS: content rating description */
+       _("Characters in unsafe situations easily distinguishable from reality") },
+       { "violence-fantasy",   AS_CONTENT_RATING_VALUE_MODERATE,
+       /* TRANSLATORS: content rating description */
+       _("Characters in aggressive conflict easily distinguishable from reality") },
+       { "violence-fantasy",   AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Graphic violence easily distinguishable from reality") },
+       { "violence-realistic", AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No realistic violence") },
+       { "violence-realistic", AS_CONTENT_RATING_VALUE_MILD,
+       /* TRANSLATORS: content rating description */
+       _("Mildly realistic characters in unsafe situations") },
+       { "violence-realistic", AS_CONTENT_RATING_VALUE_MODERATE,
+       /* TRANSLATORS: content rating description */
+       _("Depictions of realistic characters in aggressive conflict") },
+       { "violence-realistic", AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Graphic violence involving realistic characters") },
+       { "violence-bloodshed", AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No bloodshed") },
+       { "violence-bloodshed", AS_CONTENT_RATING_VALUE_MILD,
+       /* TRANSLATORS: content rating description */
+       _("Unrealistic bloodshed") },
+       { "violence-bloodshed", AS_CONTENT_RATING_VALUE_MODERATE,
+       /* TRANSLATORS: content rating description */
+       _("Realistic bloodshed") },
+       { "violence-bloodshed", AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Depictions of bloodshed and the mutilation of body parts") },
+       { "violence-sexual",    AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No sexual violence") },
+       { "violence-sexual",    AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Rape or other violent sexual behavior") },
+       { "drugs-alcohol",      AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No references to alcohol") },
+       { "drugs-alcohol",      AS_CONTENT_RATING_VALUE_MILD,
+       /* TRANSLATORS: content rating description */
+       _("References to alcoholic beverages") },
+       { "drugs-alcohol",      AS_CONTENT_RATING_VALUE_MODERATE,
+       /* TRANSLATORS: content rating description */
+       _("Use of alcoholic beverages") },
+       { "drugs-narcotics",    AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No references to illicit drugs") },
+       { "drugs-narcotics",    AS_CONTENT_RATING_VALUE_MILD,
+       /* TRANSLATORS: content rating description */
+       _("References to illicit drugs") },
+       { "drugs-narcotics",    AS_CONTENT_RATING_VALUE_MODERATE,
+       /* TRANSLATORS: content rating description */
+       _("Use of illicit drugs") },
+       { "drugs-tobacco",      AS_CONTENT_RATING_VALUE_MILD,
+       /* TRANSLATORS: content rating description */
+       _("References to tobacco products") },
+       { "drugs-tobacco",      AS_CONTENT_RATING_VALUE_MODERATE,
+       /* TRANSLATORS: content rating description */
+       _("Use of tobacco products") },
+       { "sex-nudity",         AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No nudity of any sort") },
+       { "sex-nudity",         AS_CONTENT_RATING_VALUE_MILD,
+       /* TRANSLATORS: content rating description */
+       _("Brief artistic nudity") },
+       { "sex-nudity",         AS_CONTENT_RATING_VALUE_MODERATE,
+       /* TRANSLATORS: content rating description */
+       _("Prolonged nudity") },
+       { "sex-themes",         AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No references or depictions of sexual nature") },
+       { "sex-themes",         AS_CONTENT_RATING_VALUE_MILD,
+       /* TRANSLATORS: content rating description */
+       _("Provocative references or depictions") },
+       { "sex-themes",         AS_CONTENT_RATING_VALUE_MODERATE,
+       /* TRANSLATORS: content rating description */
+       _("Sexual references or depictions") },
+       { "sex-themes",         AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Graphic sexual behavior") },
+       { "language-profanity", AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No profanity of any kind") },
+       { "language-profanity", AS_CONTENT_RATING_VALUE_MILD,
+       /* TRANSLATORS: content rating description */
+       _("Mild or infrequent use of profanity") },
+       { "language-profanity", AS_CONTENT_RATING_VALUE_MODERATE,
+       /* TRANSLATORS: content rating description */
+       _("Moderate use of profanity") },
+       { "language-profanity", AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Strong or frequent use of profanity") },
+       { "language-humor",     AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No innappropriate humor") },
+       { "language-humor",     AS_CONTENT_RATING_VALUE_MILD,
+       /* TRANSLATORS: content rating description */
+       _("Slapstick humor") },
+       { "language-humor",     AS_CONTENT_RATING_VALUE_MODERATE,
+       /* TRANSLATORS: content rating description */
+       _("Vulgar or bathroom humor") },
+       { "language-humor",     AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Mature or sexual humor") },
+       { "language-discrimination", AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No discriminatory language of any kind") },
+       { "language-discrimination", AS_CONTENT_RATING_VALUE_MILD,
+       /* TRANSLATORS: content rating description */
+       _("Negativity towards a specific group of people") },
+       { "language-discrimination", AS_CONTENT_RATING_VALUE_MODERATE,
+       /* TRANSLATORS: content rating description */
+       _("Discrimination designed to cause emotional harm") },
+       { "language-discrimination", AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Explicit discrimination based on gender, sexuality, race or religion") },
+       { "money-advertising", AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No advertising of any kind") },
+       { "money-advertising", AS_CONTENT_RATING_VALUE_MILD,
+       /* TRANSLATORS: content rating description */
+       _("Product placement") },
+       { "money-advertising", AS_CONTENT_RATING_VALUE_MODERATE,
+       /* TRANSLATORS: content rating description */
+       _("Explicit references to specific brands or trademarked products") },
+       { "money-advertising", AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Players are encouraged to purchase specific real-world items") },
+       { "money-gambling",     AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No gambling of any kind") },
+       { "money-gambling",     AS_CONTENT_RATING_VALUE_MILD,
+       /* TRANSLATORS: content rating description */
+       _("Gambling on random events using tokens or credits") },
+       { "money-gambling",     AS_CONTENT_RATING_VALUE_MODERATE,
+       /* TRANSLATORS: content rating description */
+       _("Gambling using \"play\" money") },
+       { "money-gambling",     AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Gambling using real money") },
+       { "money-purchasing",   AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No ability to spend money") },
+       { "money-purchasing",   AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Ability to spend real money in-game") },
+       { "social-chat",        AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No way to chat with other players") },
+       { "social-chat",        AS_CONTENT_RATING_VALUE_MILD,
+       /* TRANSLATORS: content rating description */
+       _("Player-to-player game interactions without chat functionality") },
+       { "social-chat",        AS_CONTENT_RATING_VALUE_MODERATE,
+       /* TRANSLATORS: content rating description */
+       _("Player-to-player preset interactions without chat functionality") },
+       { "social-chat",        AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Uncontrolled chat functionality between players") },
+       { "social-audio",       AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No way to talk with other players") },
+       { "social-audio",       AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Uncontrolled audio or video chat functionality between players") },
+       { "social-contacts",    AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No sharing of social network usernames or email addresses") },
+       { "social-contacts",    AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Sharing social network usernames or email addresses") },
+       { "social-info",        AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No sharing of user information with 3rd parties") },
+       { "social-info",        AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Sharing user information with 3rd parties") },
+       { "social-location",    AS_CONTENT_RATING_VALUE_NONE,
+       /* TRANSLATORS: content rating description */
+       _("No sharing of physical location to other users") },
+       { "social-location",    AS_CONTENT_RATING_VALUE_INTENSE,
+       /* TRANSLATORS: content rating description */
+       _("Sharing physical location to other users") },
+       { NULL, 0, NULL } };
+       for (i = 0; tab[i].id != NULL; i++) {
+               if (g_strcmp0 (tab[i].id, id) == 0 && tab[i].value == value)
+                       return tab[i].desc;
+       }
+       return NULL;
+}
+
+/* data obtained from https://en.wikipedia.org/wiki/Video_game_rating_system */
+const gchar *
+gs_utils_content_rating_age_to_str (GsContentRatingSystem system, guint age)
+{
+       if (system == GS_CONTENT_RATING_SYSTEM_INCAA) {
+               if (age >= 18)
+                       return "+18";
+               if (age >= 13)
+                       return "+13";
+               return "ATP";
+       }
+       if (system == GS_CONTENT_RATING_SYSTEM_ACB) {
+               if (age >= 18)
+                       return "R18+";
+               if (age >= 15)
+                       return "MA15+";
+               return "PG";
+       }
+       if (system == GS_CONTENT_RATING_SYSTEM_DJCTQ) {
+               if (age >= 18)
+                       return "18";
+               if (age >= 16)
+                       return "16";
+               if (age >= 14)
+                       return "14";
+               if (age >= 12)
+                       return "12";
+               if (age >= 10)
+                       return "10";
+               return "L";
+       }
+       if (system == GS_CONTENT_RATING_SYSTEM_GSRR) {
+               if (age >= 18)
+                       return "限制";
+               if (age >= 15)
+                       return "輔15";
+               if (age >= 12)
+                       return "輔12";
+               if (age >= 6)
+                       return "保護";
+               return "普通";
+       }
+       if (system == GS_CONTENT_RATING_SYSTEM_PEGI) {
+               if (age >= 18)
+                       return "18";
+               if (age >= 16)
+                       return "16";
+               if (age >= 12)
+                       return "12";
+               if (age >= 7)
+                       return "7";
+               if (age >= 3)
+                       return "3";
+               return NULL;
+       }
+       if (system == GS_CONTENT_RATING_SYSTEM_KAVI) {
+               if (age >= 18)
+                       return "18+";
+               if (age >= 16)
+                       return "16+";
+               if (age >= 12)
+                       return "12+";
+               if (age >= 7)
+                       return "7+";
+               if (age >= 3)
+                       return "3+";
+               return NULL;
+       }
+       if (system == GS_CONTENT_RATING_SYSTEM_USK) {
+               if (age >= 18)
+                       return "18";
+               if (age >= 16)
+                       return "16";
+               if (age >= 12)
+                       return "12";
+               if (age >= 6)
+                       return "6";
+               return "0";
+       }
+       if (system == GS_CONTENT_RATING_SYSTEM_ESRA) {
+               if (age >= 25)
+                       return "+25";
+               if (age >= 18)
+                       return "+18";
+               if (age >= 12)
+                       return "+12";
+               if (age >= 7)
+                       return "+7";
+               if (age >= 3)
+                       return "+3";
+               return NULL;
+       }
+       if (system == GS_CONTENT_RATING_SYSTEM_CERO) {
+               if (age >= 18)
+                       return "Z";
+               if (age >= 17)
+                       return "D";
+               if (age >= 15)
+                       return "C";
+               if (age >= 12)
+                       return "B";
+               return "A";
+       }
+       if (system == GS_CONTENT_RATING_SYSTEM_OFLCNZ) {
+               if (age >= 18)
+                       return "R18";
+               if (age >= 16)
+                       return "R16";
+               if (age >= 15)
+                       return "R15";
+               if (age >= 13)
+                       return "R13";
+               return "G";
+       }
+       if (system == GS_CONTENT_RATING_SYSTEM_RUSSIA) {
+               if (age >= 18)
+                       return "18+";
+               if (age >= 16)
+                       return "16+";
+               if (age >= 12)
+                       return "12+";
+               if (age >= 6)
+                       return "6+";
+               return "0+";
+       }
+       if (system == GS_CONTENT_RATING_SYSTEM_MDA) {
+               if (age >= 18)
+                       return "M18";
+               if (age >= 16)
+                       return "ADV";
+               return "General";
+       }
+       if (system == GS_CONTENT_RATING_SYSTEM_GRAC) {
+               if (age >= 18)
+                       return "18";
+               if (age >= 15)
+                       return "15";
+               if (age >= 12)
+                       return "12";
+               return "ALL";
+       }
+       if (system == GS_CONTENT_RATING_SYSTEM_ESRB) {
+               if (age >= 18)
+                       return "AO";
+               if (age >= 17)
+                       return "M";
+               if (age >= 13)
+                       return "T";
+               if (age >= 10)
+                       return "E10+";
+               if (age >= 6)
+                       return "E";
+               return "EC";
+       }
+       /* IARC = everything else */
+       if (age >= 18)
+               return "18+";
+       if (age >= 16)
+               return "16+";
+       if (age >= 12)
+               return "12+";
+       if (age >= 7)
+               return "7+";
+       if (age >= 3)
+               return "3+";
+       return NULL;
+}
+
+/* data obtained from https://en.wikipedia.org/wiki/Video_game_rating_system */
+GsContentRatingSystem
+gs_utils_content_rating_system_from_locale (const gchar *locale)
+{
+       g_auto(GStrv) split = g_strsplit (locale, "_", -1);
+
+       /* Argentina */
+       if (g_strcmp0 (split[0], "ar") == 0)
+               return GS_CONTENT_RATING_SYSTEM_INCAA;
+
+       /* Australia */
+       if (g_strcmp0 (split[0], "au") == 0)
+               return GS_CONTENT_RATING_SYSTEM_ACB;
+
+       /* Brazil */
+       if (g_strcmp0 (split[0], "br") == 0)
+               return GS_CONTENT_RATING_SYSTEM_DJCTQ;
+
+       /* Taiwan */
+       if (g_strcmp0 (locale, "zh_TW") == 0)
+               return GS_CONTENT_RATING_SYSTEM_GSRR;
+
+       /* Europe (but not Finland or Germany), India, Israel,
+        * Pakistan, Quebec, South Africa */
+       if (g_strcmp0 (locale, "en_GB") == 0 ||
+           g_strcmp0 (split[0], "gb") == 0 ||
+           g_strcmp0 (split[0], "al") == 0 ||
+           g_strcmp0 (split[0], "ad") == 0 ||
+           g_strcmp0 (split[0], "am") == 0 ||
+           g_strcmp0 (split[0], "at") == 0 ||
+           g_strcmp0 (split[0], "az") == 0 ||
+           g_strcmp0 (split[0], "by") == 0 ||
+           g_strcmp0 (split[0], "be") == 0 ||
+           g_strcmp0 (split[0], "ba") == 0 ||
+           g_strcmp0 (split[0], "bg") == 0 ||
+           g_strcmp0 (split[0], "hr") == 0 ||
+           g_strcmp0 (split[0], "cy") == 0 ||
+           g_strcmp0 (split[0], "cz") == 0 ||
+           g_strcmp0 (split[0], "dk") == 0 ||
+           g_strcmp0 (split[0], "ee") == 0 ||
+           g_strcmp0 (split[0], "fr") == 0 ||
+           g_strcmp0 (split[0], "ge") == 0 ||
+           g_strcmp0 (split[0], "gr") == 0 ||
+           g_strcmp0 (split[0], "hu") == 0 ||
+           g_strcmp0 (split[0], "is") == 0 ||
+           g_strcmp0 (split[0], "it") == 0 ||
+           g_strcmp0 (split[0], "kz") == 0 ||
+           g_strcmp0 (split[0], "xk") == 0 ||
+           g_strcmp0 (split[0], "lv") == 0 ||
+           g_strcmp0 (split[0], "fl") == 0 ||
+           g_strcmp0 (split[0], "lu") == 0 ||
+           g_strcmp0 (split[0], "lt") == 0 ||
+           g_strcmp0 (split[0], "mk") == 0 ||
+           g_strcmp0 (split[0], "mt") == 0 ||
+           g_strcmp0 (split[0], "md") == 0 ||
+           g_strcmp0 (split[0], "mc") == 0 ||
+           g_strcmp0 (split[0], "me") == 0 ||
+           g_strcmp0 (split[0], "nl") == 0 ||
+           g_strcmp0 (split[0], "no") == 0 ||
+           g_strcmp0 (split[0], "pl") == 0 ||
+           g_strcmp0 (split[0], "pt") == 0 ||
+           g_strcmp0 (split[0], "ro") == 0 ||
+           g_strcmp0 (split[0], "sm") == 0 ||
+           g_strcmp0 (split[0], "rs") == 0 ||
+           g_strcmp0 (split[0], "sk") == 0 ||
+           g_strcmp0 (split[0], "si") == 0 ||
+           g_strcmp0 (split[0], "es") == 0 ||
+           g_strcmp0 (split[0], "se") == 0 ||
+           g_strcmp0 (split[0], "ch") == 0 ||
+           g_strcmp0 (split[0], "tr") == 0 ||
+           g_strcmp0 (split[0], "ua") == 0 ||
+           g_strcmp0 (split[0], "va") == 0 ||
+           g_strcmp0 (split[0], "in") == 0 ||
+           g_strcmp0 (split[0], "il") == 0 ||
+           g_strcmp0 (split[0], "pk") == 0 ||
+           g_strcmp0 (split[0], "za") == 0)
+               return GS_CONTENT_RATING_SYSTEM_PEGI;
+
+       /* Finland */
+       if (g_strcmp0 (split[0], "fi") == 0)
+               return GS_CONTENT_RATING_SYSTEM_KAVI;
+
+       /* Germany */
+       if (g_strcmp0 (split[0], "de") == 0)
+               return GS_CONTENT_RATING_SYSTEM_USK;
+
+       /* Iran */
+       if (g_strcmp0 (split[0], "ir") == 0)
+               return GS_CONTENT_RATING_SYSTEM_ESRA;
+
+       /* Japan */
+       if (g_strcmp0 (split[0], "jp") == 0)
+               return GS_CONTENT_RATING_SYSTEM_CERO;
+
+       /* New Zealand */
+       if (g_strcmp0 (split[0], "nz") == 0)
+               return GS_CONTENT_RATING_SYSTEM_OFLCNZ;
+
+       /* Russia: Content rating law */
+       if (g_strcmp0 (split[0], "ru") == 0)
+               return GS_CONTENT_RATING_SYSTEM_RUSSIA;
+
+       /* Singapore */
+       if (g_strcmp0 (split[0], "sg") == 0)
+               return GS_CONTENT_RATING_SYSTEM_MDA;
+
+       /* South Korea */
+       if (g_strcmp0 (split[0], "kr") == 0)
+               return GS_CONTENT_RATING_SYSTEM_GRAC;
+
+       /* USA, Canada, Mexico */
+       if (g_strcmp0 (locale, "en_US") == 0 ||
+           g_strcmp0 (split[0], "us") == 0 ||
+           g_strcmp0 (split[0], "ca") == 0 ||
+           g_strcmp0 (split[0], "mx") == 0)
+               return GS_CONTENT_RATING_SYSTEM_ESRB;
+
+       /* everything else is IARC */
+       return GS_CONTENT_RATING_SYSTEM_IARC;
+}
diff --git a/src/gs-content-rating.h b/src/gs-content-rating.h
new file mode 100644
index 0000000..3d8f701
--- /dev/null
+++ b/src/gs-content-rating.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2015-2016 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __GS_CONTENT_RATING_H
+#define __GS_CONTENT_RATING_H
+
+G_BEGIN_DECLS
+
+#include <appstream-glib.h>
+#include <glib-object.h>
+
+typedef enum {
+       GS_CONTENT_RATING_SYSTEM_UNKNOWN,
+       GS_CONTENT_RATING_SYSTEM_INCAA,
+       GS_CONTENT_RATING_SYSTEM_ACB,
+       GS_CONTENT_RATING_SYSTEM_DJCTQ,
+       GS_CONTENT_RATING_SYSTEM_GSRR,
+       GS_CONTENT_RATING_SYSTEM_PEGI,
+       GS_CONTENT_RATING_SYSTEM_KAVI,
+       GS_CONTENT_RATING_SYSTEM_USK,
+       GS_CONTENT_RATING_SYSTEM_ESRA,
+       GS_CONTENT_RATING_SYSTEM_CERO,
+       GS_CONTENT_RATING_SYSTEM_OFLCNZ,
+       GS_CONTENT_RATING_SYSTEM_RUSSIA,
+       GS_CONTENT_RATING_SYSTEM_MDA,
+       GS_CONTENT_RATING_SYSTEM_GRAC,
+       GS_CONTENT_RATING_SYSTEM_ESRB,
+       GS_CONTENT_RATING_SYSTEM_IARC,
+       /*< private >*/
+       GS_CONTENT_RATING_SYSTEM_LAST
+} GsContentRatingSystem;
+
+const gchar *gs_utils_content_rating_age_to_str (GsContentRatingSystem system,
+                                                guint age);
+GsContentRatingSystem gs_utils_content_rating_system_from_locale (const gchar *locale);
+const gchar *gs_content_rating_key_value_to_str (const gchar *id,
+                                                AsContentRatingValue value);
+const gchar *gs_content_rating_system_to_str (GsContentRatingSystem system);
+
+G_END_DECLS
+
+#endif /* __GS_CONTENT_RATING_H */
+
+/* vim: set noexpandtab: */
diff --git a/src/gs-shell-details.c b/src/gs-shell-details.c
index ed4f3e0..84b5ca5 100644
--- a/src/gs-shell-details.c
+++ b/src/gs-shell-details.c
@@ -26,6 +26,7 @@
 #include <glib/gi18n.h>
 
 #include "gs-common.h"
+#include "gs-content-rating.h"
 
 #include "gs-shell-details.h"
 #include "gs-app-private.h"
@@ -1329,15 +1330,33 @@ static void
 gs_shell_details_refresh_content_rating (GsShellDetails *self)
 {
        AsContentRating *content_rating;
+       GsContentRatingSystem system;
        guint age = 0;
+       gchar *str;
+       const gchar *display = NULL;
+       g_autofree gchar *locale = NULL;
+
+       /* get the content rating system from the locale */
+       locale = g_strdup (setlocale (LC_MESSAGES, NULL));
+       str = g_strstr_len (locale, -1, ".UTF-8");
+       if (str != NULL)
+               *str = '\0';
+       str = g_strstr_len (locale, -1, ".utf8");
+       if (str != NULL)
+               *str = '\0';
+       system = gs_utils_content_rating_system_from_locale (locale);
+       g_debug ("content rating system is guessed as %s from %s",
+                gs_content_rating_system_to_str (system),
+                locale);
 
        /* only show the button if a game and has a content rating */
        content_rating = gs_app_get_content_rating (self->app);
-       if (content_rating != NULL)
+       if (content_rating != NULL) {
                age = as_content_rating_get_minimum_age (content_rating);
-       if (age > 3) {
-               g_autofree gchar *tmp = g_strdup_printf ("%u+", age);
-               gtk_button_set_label (GTK_BUTTON (self->button_details_rating_value), tmp);
+               display = gs_utils_content_rating_age_to_str (system, age);
+       }
+       if (display != NULL) {
+               gtk_button_set_label (GTK_BUTTON (self->button_details_rating_value), display);
                gtk_widget_set_visible (self->button_details_rating_value, TRUE);
                gtk_widget_set_visible (self->label_details_rating_title, TRUE);
                gs_shell_details_content_rating_set_css (self->button_details_rating_value, age);
@@ -1819,7 +1838,7 @@ gs_shell_details_content_rating_button_cb (GtkWidget *widget, GsShellDetails *se
                        value = as_content_rating_get_value (cr, id_map[j].ids[i]);
                        if (value < value_bad)
                                continue;
-                       tmp = gs_utils_content_rating_kv_to_str (id_map[j].ids[i], value);
+                       tmp = gs_content_rating_key_value_to_str (id_map[j].ids[i], value);
                        g_string_append_printf (str, "• %s\n", tmp);
                        break;
                }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]