From 4928feaea89cd409840a13868296f098975ebd02 Mon Sep 17 00:00:00 2001 From: TheRolf Date: Thu, 2 Sep 2021 12:06:06 +0200 Subject: [PATCH] Fixed traffic infos with localised date parser --- .../activities/Main/TrafficController.java | 330 ++++++------- .../vue/adapters/TrafficAdapter.java | 436 ++++++++++++------ app/src/main/res/layout/expandable_item.xml | 114 ++--- app/src/main/res/values-es/strings.xml | 124 ++--- app/src/main/res/values-fr/strings.xml | 124 ++--- app/src/main/res/values/strings.xml | 146 +++--- 6 files changed, 711 insertions(+), 563 deletions(-) diff --git a/app/src/main/java/com/therolf/optymoNext/controller/activities/Main/TrafficController.java b/app/src/main/java/com/therolf/optymoNext/controller/activities/Main/TrafficController.java index 0c48712..811c9b9 100644 --- a/app/src/main/java/com/therolf/optymoNext/controller/activities/Main/TrafficController.java +++ b/app/src/main/java/com/therolf/optymoNext/controller/activities/Main/TrafficController.java @@ -1,162 +1,168 @@ -package com.therolf.optymoNext.controller.activities.Main; - -import android.os.AsyncTask; -import android.util.Log; -import android.view.View; -import android.widget.ExpandableListView; -import android.widget.ProgressBar; -import android.widget.Toast; - -import androidx.appcompat.app.AppCompatActivity; - -import com.therolf.optymoNext.R; -import com.therolf.optymoNext.controller.global.Utility; -import com.therolf.optymoNext.vue.adapters.TrafficAdapter; - -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.jsoup.select.Elements; - -import java.util.ArrayList; - -@SuppressWarnings("unused") -public class TrafficController implements ExpandableListView.OnGroupExpandListener, ExpandableListView.OnGroupCollapseListener { - - private AppCompatActivity context; - - private ArrayList data = new ArrayList<>(); - private TrafficAdapter trafficAdapter; - private ExpandableListView listView; - - private ProgressBar progressBar; - - private TrafficInfoRequest request; - - TrafficController(AppCompatActivity context) { - this.context = context; - - trafficAdapter = new TrafficAdapter(context, R.string.main_traffic_info, data); - listView = context.findViewById(R.id.main_traffic_info_listview); - listView.setAdapter(trafficAdapter); - listView.setOnGroupExpandListener(this); - listView.setOnGroupCollapseListener(this); - - progressBar = context.findViewById(R.id.main_traffic_info_progressbar); - progressBar.setVisibility(View.GONE); - } - - @Override - public void onGroupExpand(int groupPosition) { - if(request != null && !request.isCancelled()) { - request.cancel(true); - } - - request = new TrafficInfoRequest(this); - request.execute(); - } - - @Override - public void onGroupCollapse(int groupPosition) { - // cancel request - if(request != null && !request.isCancelled()) { - request.cancel(true); - } - - // notify update - context.runOnUiThread(() -> { - data.clear(); - trafficAdapter.notifyDataSetChanged(); - Utility.setListViewHeightBasedOnChildren(listView); - }); - } - - public static class TrafficInfoRequest extends AsyncTask { - - private TrafficController tc; - - TrafficInfoRequest(TrafficController tc) { - this.tc = tc; - } - - @Override - protected String doInBackground(Void... voids) { - String result = null; - - // clear data - tc.data.clear(); - - // notify update - tc.context.runOnUiThread(() -> { - tc.progressBar.setVisibility(View.VISIBLE); // visible visibility - tc.trafficAdapter.notifyDataSetChanged(); - Utility.setListViewHeightBasedOnChildren(tc.listView); - }); - - // read traffic RSS feed URL - try { - result = Utility.readUrl("https://www.optymo.fr/infos_trafic/feed"); - - } catch (Exception e) { - e.printStackTrace(); - } - - return result; - } - - @Override - protected void onPostExecute(String page) { - super.onPostExecute(page); - - // gone visibility - tc.context.runOnUiThread(() -> tc.progressBar.setVisibility(View.GONE)); - - if(page == null) { - Toast.makeText(tc.context, R.string.error_occured, Toast.LENGTH_SHORT).show(); - return; - } - - Document document = Jsoup.parse(page), dateDocument; - Elements items = document.getElementsByTag("item"), dates; - String body, date, lines, content, url, itemHtml; - for(Element item : items) { -// Log.d("optmyonext", item.html()); - dateDocument = Jsoup.parse(item.getElementsByTag("description").get(0).text()); - body = dateDocument.body().text(); - - int lineIndex = body.indexOf("Lignes"); - - if(lineIndex == -1) { - date = body; - lines = ""; - } else { - date = body.substring(0, lineIndex); - lines = body.substring(lineIndex); - } - content = item.getElementsByTag("title").get(0).text(); - - itemHtml = item.html(); - url = itemHtml.substring(itemHtml.indexOf("")+6, itemHtml.indexOf("")); - url = url.replace("", ""); - Log.d("optmyonext", "url:" + url); - - // add string - tc.data.add(new TrafficAdapter.TrafficInfo(date, lines, content, url)); - } - - // notify update - tc.context.runOnUiThread(() -> { - tc.trafficAdapter.notifyDataSetChanged(); - Utility.setListViewHeightBasedOnChildren(tc.listView); - }); - } - - @Override - protected void onCancelled() { - super.onCancelled(); - - // gone visibility - tc.context.runOnUiThread(() -> tc.progressBar.setVisibility(View.GONE)); - } - } -} +package com.therolf.optymoNext.controller.activities.Main; + +import android.text.TextUtils; +import android.view.View; +import android.widget.ExpandableListView; +import android.widget.ProgressBar; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; + +import com.android.volley.Request; +import com.android.volley.RequestQueue; +import com.android.volley.toolbox.StringRequest; +import com.android.volley.toolbox.Volley; +import com.therolf.optymoNext.R; +import com.therolf.optymoNext.controller.global.Utility; +import com.therolf.optymoNext.vue.adapters.TrafficAdapter; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +@SuppressWarnings("unused") +public class TrafficController implements ExpandableListView.OnGroupExpandListener, ExpandableListView.OnGroupCollapseListener { + + private AppCompatActivity context; + + private ArrayList data = new ArrayList<>(); + private TrafficAdapter trafficAdapter; + private ExpandableListView listView; + + private static final String TRAFFIC_REQUEST_TAG = "request_traffic"; + private StringRequest trafficRequest; + private RequestQueue trafficQueue; + + private static final Comparator LINE_COMPARATOR = (o1, o2) -> { + try { + int i1 = Integer.parseInt(o1); + int i2 = Integer.parseInt(o2); + + return Integer.compare(i1, i2); + } catch (NumberFormatException e) { + e.printStackTrace(); + return 0; + } + }; + + private static final Comparator ALERT_COMPARATOR = (o1, o2) -> -o1.getPublicationDate().compareTo(o2.getPublicationDate()); + + private static final String TRAFFIC_URL = "https://app.mecatran.com/utw/ws/alerts/active/belfort?preferredLang=fr&includeRoutes=true&includeStops=true&apiKey=76350b70682e051e6709782b551f5437173f1957"; + private static final String TRAFFIC_PAGE_ROOT = "https://www.optymo.fr/infos_trafic/#"; + + // routes color and text color https://app.mecatran.com/utw/ws/gtfs/routes/belfort?includeAgencies=true&apiKey=76350b70682e051e6709782b551f5437173f1957 + + private ProgressBar progressBar; + + TrafficController(AppCompatActivity context) { + this.context = context; + + trafficAdapter = new TrafficAdapter(context, R.string.main_traffic_info, data); + listView = context.findViewById(R.id.main_traffic_info_listview); + listView.setAdapter(trafficAdapter); + listView.setOnGroupExpandListener(this); + listView.setOnGroupCollapseListener(this); + + progressBar = context.findViewById(R.id.main_traffic_info_progressbar); + progressBar.setVisibility(View.GONE); + + this.trafficQueue = Volley.newRequestQueue(context); + this.trafficRequest = null; + } + + @Override + public void onGroupExpand(int groupPosition) { + trafficQueue.add(this.request()); + } + + private void hideProgressbar() { + this.context.runOnUiThread(() -> this.progressBar.setVisibility(View.GONE)); + } + + private void requestCancel() { + if(this.trafficRequest != null && !this.trafficRequest.isCanceled()) { + this.trafficRequest.cancel(); + } + } + + private StringRequest request() { + this.requestCancel(); + + this.data.clear(); + this.context.runOnUiThread(() -> { + this.progressBar.setVisibility(View.VISIBLE); // visible visibility + this.trafficAdapter.notifyDataSetChanged(); + Utility.setListViewHeightBasedOnChildren(this.listView); + }); + + this.trafficRequest = new StringRequest(Request.Method.GET, TRAFFIC_URL, (response) -> { + response = new String(response.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); + + this.hideProgressbar(); + + try { + JSONArray result = new JSONArray(response); + + String title, formattedActiveRange, lines, url, publicationDate, from, to; + JSONArray routes; + ArrayList linesList = new ArrayList<>(); + for(int alertIndex = 0; alertIndex < result.length(); ++alertIndex) { + JSONObject alert = result.getJSONObject(alertIndex); + + title = alert.getString("title"); + title = title.substring(0,1).toUpperCase()+title.substring(1); + formattedActiveRange = alert.getString("formattedActiveRange"); + url = TRAFFIC_PAGE_ROOT + alert.getString("id"); + publicationDate = alert.getJSONObject("apiPublication").getString("dateTime"); + + routes = alert.getJSONArray("routes"); + linesList.clear(); + for (int routeIndex = 0; routeIndex < routes.length(); ++routeIndex) { + linesList.add(routes.getJSONObject(routeIndex).getString("shortName")); + } + Collections.sort(linesList, LINE_COMPARATOR); + lines = TextUtils.join(", ", linesList); + + // eventually add this to the data array list + TrafficAdapter.TrafficInfo infos = new TrafficAdapter.TrafficInfo(formattedActiveRange, lines, title, url, publicationDate); + infos.setFrom(alert.optString("activeFrom")); + infos.setTo(alert.optString("activeTo")); + this.data.add(infos); + } + } catch (JSONException e) { + Toast.makeText(this.context, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show(); + e.printStackTrace(); + } + + Collections.sort(this.data, ALERT_COMPARATOR); + + // notify update + this.context.runOnUiThread(() -> { + this.trafficAdapter.notifyDataSetChanged(); + Utility.setListViewHeightBasedOnChildren(this.listView); + }); + }, error -> { + this.hideProgressbar(); + error.printStackTrace(); + }); + + return this.trafficRequest; + } + + @Override + public void onGroupCollapse(int groupPosition) { + this.requestCancel(); + + // notify update + context.runOnUiThread(() -> { + data.clear(); + trafficAdapter.notifyDataSetChanged(); + Utility.setListViewHeightBasedOnChildren(listView); + }); + } +} diff --git a/app/src/main/java/com/therolf/optymoNext/vue/adapters/TrafficAdapter.java b/app/src/main/java/com/therolf/optymoNext/vue/adapters/TrafficAdapter.java index 59ed395..499181c 100644 --- a/app/src/main/java/com/therolf/optymoNext/vue/adapters/TrafficAdapter.java +++ b/app/src/main/java/com/therolf/optymoNext/vue/adapters/TrafficAdapter.java @@ -1,153 +1,283 @@ -package com.therolf.optymoNext.vue.adapters; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.text.Html; -import android.text.method.LinkMovementMethod; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseExpandableListAdapter; -import android.widget.ImageView; -import android.widget.TextView; - -import com.therolf.optymoNext.R; - -import java.util.ArrayList; - -@SuppressWarnings("unused") -public class TrafficAdapter extends BaseExpandableListAdapter { - - private Context context; - private int titleId; - private ArrayList data; - - private Drawable upArrow; - private Drawable downArrow; - - public TrafficAdapter(Context context, int titleId, ArrayList data) { - this.context = context; - this.titleId = titleId; - this.data = data; - this.upArrow = context.getResources().getDrawable(R.drawable.ic_arrow_up_red); - this.downArrow = context.getResources().getDrawable(R.drawable.ic_arrow_down_red); - } - - @Override - public int getGroupCount() { - return 1; - } - - @Override - public int getChildrenCount(int groupPosition) { - return data.size(); - } - - @Override - public Object getGroup(int groupPosition) { - return data; - } - - @Override - public Object getChild(int groupPosition, int childPosition) { - return data.get(childPosition); - } - - @Override - public long getGroupId(int groupPosition) { - return groupPosition; - } - - @Override - public long getChildId(int groupPosition, int childPosition) { - return childPosition; - } - - @Override - public boolean hasStableIds() { - return false; - } - - @SuppressLint("InflateParams") - @Override - public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { - if(convertView == null) { - LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - //noinspection ConstantConditions - convertView = inflater.inflate(R.layout.expandable_title, null); - } - - ((TextView) convertView.findViewById(R.id.expandable_title)).setText(titleId); - - ImageView arrow = convertView.findViewById(R.id.expandable_arrow); - if(isExpanded) { - arrow.setImageDrawable(upArrow); - } else { - arrow.setImageDrawable(downArrow); - } - - return convertView; - } - - @SuppressLint("InflateParams") - @Override - public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { - if(convertView == null) { - LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - //noinspection ConstantConditions - convertView = inflater.inflate(R.layout.expandable_item, null); - } - - // update date - ((TextView) convertView.findViewById(R.id.expandable_date)).setText(data.get(childPosition).date); - - // update line - if (data.get(childPosition).lines.equals("")) { - convertView.findViewById(R.id.expandable_lines).setVisibility(View.GONE); - } else { - convertView.findViewById(R.id.expandable_lines).setVisibility(View.VISIBLE); - ((TextView) convertView.findViewById(R.id.expandable_lines)).setText(data.get(childPosition).lines); - } - - // update content - ((TextView) convertView.findViewById(R.id.expandable_content)).setText(data.get(childPosition).content); - - // update more infos url - TextView moreInfos = convertView.findViewById(R.id.expandable_more_infos); - if(data.get(childPosition).url != null && data.get(childPosition).url.startsWith("http")) { - CharSequence text = moreInfos.getText(); - String linkText = "" + text + ""; - moreInfos.setMovementMethod(LinkMovementMethod.getInstance()); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - moreInfos.setText(Html.fromHtml(linkText, Html.FROM_HTML_MODE_LEGACY)); - } else { - moreInfos.setText(Html.fromHtml(linkText)); - } - } else { - moreInfos.setVisibility(View.INVISIBLE); - } - - return convertView; - } - - @Override - public boolean isChildSelectable(int groupPosition, int childPosition) { - return false; - } - - public static class TrafficInfo { - String date; - String lines; - String content; - String url; - - public TrafficInfo(String date, String lines, String content, String url) { - this.date = date; - this.lines = lines; - this.content = content; - this.url = url; - } - } -} +package com.therolf.optymoNext.vue.adapters; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.text.Html; +import android.text.Spannable; +import android.text.TextPaint; +import android.text.method.LinkMovementMethod; +import android.text.style.URLSpan; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseExpandableListAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +import com.therolf.optymoNext.R; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +@SuppressWarnings("unused") +public class TrafficAdapter extends BaseExpandableListAdapter { + + private Context context; + private int titleId; + private ArrayList data; + + private Drawable upArrow; + private Drawable downArrow; + + public TrafficAdapter(Context context, int titleId, ArrayList data) { + this.context = context; + this.titleId = titleId; + this.data = data; + this.upArrow = context.getResources().getDrawable(R.drawable.ic_arrow_up_red); + this.downArrow = context.getResources().getDrawable(R.drawable.ic_arrow_down_red); + } + + @Override + public int getGroupCount() { + return 1; + } + + @Override + public int getChildrenCount(int groupPosition) { + return data.size(); + } + + @Override + public Object getGroup(int groupPosition) { + return data; + } + + @Override + public Object getChild(int groupPosition, int childPosition) { + return data.get(childPosition); + } + + @Override + public long getGroupId(int groupPosition) { + return groupPosition; + } + + @Override + public long getChildId(int groupPosition, int childPosition) { + return childPosition; + } + + @Override + public boolean hasStableIds() { + return false; + } + + @SuppressLint("InflateParams") + @Override + public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { + if(convertView == null) { + LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + //noinspection ConstantConditions + convertView = inflater.inflate(R.layout.expandable_title, null); + } + + ((TextView) convertView.findViewById(R.id.expandable_title)).setText(titleId); + + ImageView arrow = convertView.findViewById(R.id.expandable_arrow); + if(isExpanded) { + arrow.setImageDrawable(upArrow); + } else { + arrow.setImageDrawable(downArrow); + } + + return convertView; + } + + @SuppressLint("InflateParams") + @Override + public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { + if(convertView == null) { + LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + //noinspection ConstantConditions + convertView = inflater.inflate(R.layout.expandable_item, null); + } + + TrafficAdapter.TrafficInfo info = data.get(childPosition); + + // update date + ((TextView) convertView.findViewById(R.id.expandable_date)).setText(info.getTime(context)); + + // update line + if (data.get(childPosition).lines.equals("")) { + convertView.findViewById(R.id.expandable_lines).setVisibility(View.GONE); + } else { + convertView.findViewById(R.id.expandable_lines).setVisibility(View.VISIBLE); + ((TextView) convertView.findViewById(R.id.expandable_lines)).setText(this.context.getResources().getString(R.string.main_traffic_info_lines_prefix, info.lines)); + } + + // update more infos url + TextView moreInfos = convertView.findViewById(R.id.expandable_more_infos); + TextView titleView = convertView.findViewById(R.id.expandable_content); + if(info.url != null && info.url.startsWith("http")) { + // link to more infos + CharSequence text = moreInfos.getText(); + String linkText = "" + text + ""; + moreInfos.setMovementMethod(LinkMovementMethod.getInstance()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + moreInfos.setText(Html.fromHtml(linkText, Html.FROM_HTML_MODE_LEGACY)); + } else { + moreInfos.setText(Html.fromHtml(linkText)); + } + + // link to title + titleView.setMovementMethod(LinkMovementMethod.getInstance()); + linkText = "" + info.content + ""; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + titleView.setText(Html.fromHtml(linkText, Html.FROM_HTML_MODE_LEGACY)); + } else { + titleView.setText(Html.fromHtml(linkText)); + } + + Spannable s = (Spannable) titleView.getText(); + URLSpan[] spans = s.getSpans(0, s.length(), URLSpan.class); + for (URLSpan span: spans) { + int start = s.getSpanStart(span); + int end = s.getSpanEnd(span); + s.removeSpan(span); + span = new URLSpanline_none(span.getURL()); + s.setSpan(span, start, end, 0); + } + titleView.setText(s); + } else { + // update content + titleView.setText(info.content); + moreInfos.setVisibility(View.INVISIBLE); + } + + return convertView; + } + + @Override + public boolean isChildSelectable(int groupPosition, int childPosition) { + return false; + } + + public static class TrafficInfo { + String date; + String lines; + String content; + String url; + String publicationDate; + + Date from; + Date to; + + public TrafficInfo(String date, String lines, String content, String url, String publicationDate) { + this.date = date; + this.lines = lines; + this.content = content; + this.url = url; + this.publicationDate = publicationDate; + } + + public String getPublicationDate() { + return publicationDate; + } + + private Date parse(String utc) throws ParseException { + @SuppressLint("SimpleDateFormat") + DateFormat m_ISO8601Local = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + m_ISO8601Local.setTimeZone(TimeZone.getTimeZone("UTC")); + + return m_ISO8601Local.parse(utc); + } + + public void setFrom(String from) { + try { + this.from = this.parse(from); + } catch (ParseException e) { + e.printStackTrace(); + } + } + + public void setTo(String to) { + try { + this.to = this.parse(to); + } catch (ParseException e) { + e.printStackTrace(); + } + } + + public String getTime(Context ctx) { + if(from == null && to == null) return this.date; + + String result; + + Locale locale = ctx.getResources().getConfiguration().locale; + DateFormat dayFormat = SimpleDateFormat.getDateInstance(SimpleDateFormat.MEDIUM, locale); + DateFormat timeFormat = SimpleDateFormat.getTimeInstance(SimpleDateFormat.SHORT, locale); + + String fromString = "", toString = ""; + + Calendar cal = Calendar.getInstance(); + int h, m; + int[] dates = new int[2]; + + if(from != null) { + fromString = dayFormat.format(from); + cal.setTime(from); + h = cal.get(Calendar.HOUR_OF_DAY); + m = cal.get(Calendar.MINUTE); + if((h != 0 || m != 0) && (h != 23 || m != 59)) { + fromString += " " + timeFormat.format(from); + } + dates[0] = cal.get(Calendar.DAY_OF_YEAR); + dates[1] = cal.get(Calendar.YEAR); + } + + if(to != null) { + toString = dayFormat.format(to); + cal.setTime(to); + h = cal.get(Calendar.HOUR_OF_DAY); + m = cal.get(Calendar.MINUTE); + if((h != 0 || m != 0) && (h != 23 || m != 59)) { + toString += " " + timeFormat.format(to); + } + } + + if(to != null) { + // From X to X + // or + // The X + if(cal.get(Calendar.DAY_OF_YEAR) == dates[0] && cal.get(Calendar.YEAR) == dates[1]) { + result = ctx.getResources().getString(R.string.main_traffic_info_date_same_day, fromString); + } else { + result = ctx.getResources().getString(R.string.main_traffic_info_date_from_to, fromString, toString); + } + } else { + // From X + result = ctx.getResources().getString(R.string.main_traffic_info_date_from, fromString); + } + + return result; + } + } + + private static class URLSpanline_none extends URLSpan { + public URLSpanline_none(String url) { + super(url); + } + @Override public void updateDrawState(@SuppressWarnings("NullableProblems") TextPaint ds) { + super.updateDrawState(ds); + ds.setUnderlineText(false); + } + } +} diff --git a/app/src/main/res/layout/expandable_item.xml b/app/src/main/res/layout/expandable_item.xml index 5ec66e7..a81478d 100644 --- a/app/src/main/res/layout/expandable_item.xml +++ b/app/src/main/res/layout/expandable_item.xml @@ -1,58 +1,58 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 9e0b9bd..d22d901 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -1,61 +1,65 @@ - - - AÑADIR - Añadir un favirito - %1$d favoritos actualmente - 1. Eligir una línea - 2. Eligir una parada de bus - Hermoso fondo - ¿Eleminar el favorito : %1$s? - Confirmar la eliminación - Favoritos - Icono de la applicación - Todas las paradas - Actualizado a las %1$s - Nunca actualizado - Cargando los favoritos - no - Extender para ver los favoritos - Actualizar - Icono de busqueda - Error durante el cargamento del red - error: \"%1$s\" - Cargamento del favorito %1$d/%2$d - Cargamento de la parada con el punto %1$d/%2$d - Generación del red con el XML - Generación del red con el JSON - Cargamento de la línea %1$d/%2$d - Cargamento del red - Cargamento de la parada %1$d/%2$d - si - actualización en curso… - Buscar una parada, una línea - Paradas - Proximos horarios - Cargamento de los horarios… - Otros - Mapa - PDFs de las líneas - Líneas - App hecha por TheRolf - No se encontró ningún lector de PDF. ¿Queréis descargarlo? - No se encontró ningún lector de PDF - Cancelar - Occurió un fallo. inténtelo más tarde. - Ningún resultado… - Mantener presionado para eleminar el favorito - Su ubicación es necesaria para mostrarle dónde está. - Permiso concedido - Permiso denegado - Require permiso - Notificias del tráfico - No favoritos - Más info - Mostrar la notificación con los próximos horarios - Presionar para ver los proximos horarios - URLs estáticos del %1$s - Últimos pdfs en línea - Cargamento… - Proximos horarios - Notificación persistente con los proximos horarios + + + AÑADIR + Añadir un favirito + %1$d favoritos actualmente + 1. Eligir una línea + 2. Eligir una parada de bus + Hermoso fondo + ¿Eleminar el favorito : %1$s? + Confirmar la eliminación + Favoritos + Icono de la applicación + Todas las paradas + Actualizado a las %1$s + Nunca actualizado + Cargando los favoritos + no + Extender para ver los favoritos + Actualizar + Icono de busqueda + Error durante el cargamento del red + error: \"%1$s\" + Cargamento del favorito %1$d/%2$d + Cargamento de la parada con el punto %1$d/%2$d + Generación del red con el XML + Generación del red con el JSON + Cargamento de la línea %1$d/%2$d + Cargamento del red + Cargamento de la parada %1$d/%2$d + si + actualización en curso… + Buscar una parada, una línea + Paradas + Proximos horarios + Cargamento de los horarios… + Otros + Mapa + PDFs de las líneas + Líneas + App hecha por TheRolf + No se encontró ningún lector de PDF. ¿Queréis descargarlo? + No se encontró ningún lector de PDF + Cancelar + Occurió un fallo. inténtelo más tarde. + Ningún resultado… + Mantener presionado para eleminar el favorito + Su ubicación es necesaria para mostrarle dónde está. + Permiso concedido + Permiso denegado + Require permiso + Notificias del tráfico + No favoritos + Más info + Mostrar la notificación con los próximos horarios + Presionar para ver los proximos horarios + URLs estáticos del %1$s + Últimos pdfs en línea + Cargamento… + Proximos horarios + Notificación persistente con los proximos horarios + Líneas : %1$s + Desde el %1$s + Desde el %1$s hasta el %2$s + El %1$s \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 2503a48..89c3b9a 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -1,61 +1,65 @@ - - - Superbe fond - Favoris - Icon de l\'app - Tous les stops - Icone de recherche - Chargement du réseau depuis le JSON - Chargement de la ligne %1$d/%2$d - Erreur lors du chargement du réseau - Chargement arrêt %1$d/%2$d - 2. Choisir un arrêt - 1. Choisir une ligne - Ajouter un favori - AJOUTER - Génération du réseau depuis le XML - Chargement du réseau - erreur : \"%1$s\" - Chargement du favoris %1$d/%2$d - Mis à jour à %1$s - Jamais mis à jour - Génération de l\'arrêt depuis le point %1$d/%2$d - Chargement des favoris… - %1$d favoris actuellement - Confirmer la supression - Supprimer le favoris : %1$s ? - oui - non - Actualiser - Étendre pour voir les favoris - Mise à jour… - Chercher un arrêt, un stop… - Arrêts - Prochains horaires - Chargement des prochains horaires… - Autres - Carte - PDFs des lignes - Lignes - App faite par TheRolf - Nous n\'avons pas trouvé de lecteur PDF. Voulez-vous le télécharger ? - Pas de lecteur PDF trouvé - Annuler - Une erreur est survenue. Réessayez plus tard. - Aucun résultat… - Maintenir appuyer pour supprimer le favori - Votre emplacement est requis pour vous montrer où vous êtes. - Permission accordée - Permission refusée - Permission requise - Infos Trafic - Pas de favoris - Plus d\'infos - Montrer la notification des prochains horaires - Appuyer pour voir les prochains horaires - URLs statiques du %1$s - Derniers PDFs en ligne - Chargement… - Prochains arrêts - Notification persistente avec les prochains arrêts + + + Superbe fond + Favoris + Icon de l\'app + Tous les stops + Icone de recherche + Chargement du réseau depuis le JSON + Chargement de la ligne %1$d/%2$d + Erreur lors du chargement du réseau + Chargement arrêt %1$d/%2$d + 2. Choisir un arrêt + 1. Choisir une ligne + Ajouter un favori + AJOUTER + Génération du réseau depuis le XML + Chargement du réseau + erreur : \"%1$s\" + Chargement du favoris %1$d/%2$d + Mis à jour à %1$s + Jamais mis à jour + Génération de l\'arrêt depuis le point %1$d/%2$d + Chargement des favoris… + %1$d favoris actuellement + Confirmer la supression + Supprimer le favoris : %1$s ? + oui + non + Actualiser + Étendre pour voir les favoris + Mise à jour… + Chercher un arrêt, un stop… + Arrêts + Prochains horaires + Chargement des prochains horaires… + Autres + Carte + PDFs des lignes + Lignes + App faite par TheRolf + Nous n\'avons pas trouvé de lecteur PDF. Voulez-vous le télécharger ? + Pas de lecteur PDF trouvé + Annuler + Une erreur est survenue. Réessayez plus tard. + Aucun résultat… + Maintenir appuyer pour supprimer le favori + Votre emplacement est requis pour vous montrer où vous êtes. + Permission accordée + Permission refusée + Permission requise + Infos Trafic + Pas de favoris + Plus d\'infos + Montrer la notification des prochains horaires + Appuyer pour voir les prochains horaires + URLs statiques du %1$s + Derniers PDFs en ligne + Chargement… + Prochains arrêts + Notification persistente avec les prochains arrêts + Lignes : %1$s + À partir du %1$s + Du %1$s au %2$s + Le %1$s \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9238f17..0d7c52a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,71 +1,75 @@ - - OptymoNext - - ptymoNext - Error loading network - Generating network from XML - Loading network from JSON - loading line %1$d/%2$d - Chargement stop %1$d/%2$d - - Favorites - - 1. Choose a line - 2. Choose a stop - ADD - - All stops - Superb background - Icon app - Search icon - Add favorite - Loading network - error: \"%1$s\" - Loading favorite %1$d/%2$d - Updated at %1$s - Never updated - Generating stop from point %1$d/%2$d - Loading favorites… - %1$d favorites now - Confirm deletion - Delete favorite: %1$s? - yes - no - Refresh - Expand to see favorites - Updating… - Search stop, line… - Stops - Next stops - Loading next times… - Others - Map - Lines PDFs - Lines - App made by TheRolf - https://therolf.fr - We didn\'t find any PDF viewer. Do you want to download it? - No PDF viewer found - Cancel - An error occurred. Please try later. - No result found… - refresh icon - Long press to delete favorite - Your location is required to show you where you are. - Permission granted - Permission denied - Permission required - OK - Traffic infos - arrow expandable list - No favorites - this is a description - More infos - Show the notification with upcoming buses - Tap on me to get next times - Static URLs of %1$s - Latest PDFs online - Loading… - Next stops - Persistent notification with next stops - + + OptymoNext + + ptymoNext + Error loading network + Generating network from XML + Loading network from JSON + loading line %1$d/%2$d + Chargement stop %1$d/%2$d + + Favorites + + 1. Choose a line + 2. Choose a stop + ADD + + All stops + Superb background + Icon app + Search icon + Add favorite + Loading network + error: \"%1$s\" + Loading favorite %1$d/%2$d + Updated at %1$s + Never updated + Generating stop from point %1$d/%2$d + Loading favorites… + %1$d favorites now + Confirm deletion + Delete favorite: %1$s? + yes + no + Refresh + Expand to see favorites + Updating… + Search stop, line… + Stops + Next stops + Loading next times… + Others + Map + Lines PDFs + Lines + App made by TheRolf + https://therolf.fr + We didn\'t find any PDF viewer. Do you want to download it? + No PDF viewer found + Cancel + An error occurred. Please try later. + No result found… + refresh icon + Long press to delete favorite + Your location is required to show you where you are. + Permission granted + Permission denied + Permission required + OK + Traffic infos + arrow expandable list + No favorites + this is a description + More infos + Show the notification with upcoming buses + Tap on me to get next times + Static URLs of %1$s + Latest PDFs online + Loading… + Next stops + Persistent notification with next stops + Lines: %1$s + From %1$s + From %1$s to %2$s + The %1$s +