When considering the typing (static, dynamic, weak, strong, etc.) of a language, there are three questions to ask. All three questions are not binary questions--sometimes or it depends are legitimate answers. (Advocates of a particular style may try to frame one or more questions as binary, with the in-between cases lumped in with one of the absolutes--usually the one deemed less desirable).
The questions are:
To what extent are typing errors detected, and are detected typing errors handled in a well-defined manner?
This question addresses the type safety of the language. A language for which the answer is always is completely type-safe; one for which the answer is never is completely type-unsafe. Note that detection may occur at runtime or at CompileTime (or ReadTime?, for languages that don't follow the standard compile/link/execute model). Also note that "well-defined manner" may include controlled failure--such as failing to compile, controlled abort of the program, raising an exception--or other behavior, such as a type coercion. Well-defined does not include any sort of UndefinedBehavior, random crashes, etc. Note that printing a diagnostic (such as a compiler warning) but continuing on without somehow fixing things is not well-defined.
When are typing errors detected?
If all typing errors are detected before the program executes, than the language is completely statically-typed. If all detection of typing errors are deferred to runtime, then we're dynamically-typed. Many languages are a mixture. Also note that some toolsets/environments will detect errors earlier than required--SmallTalk is a dynamically-typed language, but some environments will flag errors at Edit Time (not all errors can be caught this way).
How are detected typing errors handled?
If all detected typing errors are handled by failing somehow (terminating a compilation, aborting the program, raising the exception) then a language is strongly typed. If the language attempts to handle it in another way, such as a conversion to a compatible type, the language is weakly typed. Like the above two questions, this isn't a binary; a language can be mostly strongly typed (but allow implicit conversions between numeric types, or from numbers to booleans, etc.) This question only applies to operations where language-default semantics are used; operations which allow the programmer to specify what happens when a typing error is detected (i.e. an "if type X then Y else X" operator) or which allow the programmer to query whether types are compatible or not (such as instanceof in JavaLanguage) don't really affect whether or not a language is strongly or weakly typed.
I hope this is not off topic, but what is the definition of a "typing error"?
In general, a typing error is any attempt to perform an operation on an object which is inappropriate for or unsupported by the object, such as trying to multiply two strings. In some languages, multiplying strings will result in a compiler error or an exception (DoesNotUnderstand) being raised; in other languages (such as JavaScript) the implementation will try converting strings to numbers and multiplying them (if the conversion fails, at that point an exception is raised).
Still other languages may do something obnoxious, like multiplying the internal pointers which point to the strings' data--producing nonsense. This leads to UndefinedBehavior. It is ugliness like this that makes a language TypeUnsafe?
This definition appears to be somewhat in conflict with the previous use of "weakly typed." If the language handles the issue, then by definition it is not a typing error. I raise this issue only because it appears the logical conclusion from the above arguments would be in favor of type-less languages, and I don't think that is the intention; a review of the wording might help to bring out the true intent.
The intent is that a typing error occurs when an operation is attempted on an object that the object does not support. Again, multiplying strings. Converting an object to another type is one way of rectifying the problem, obviously. There is, of course, a fine line between "typing error causes type conversion" in a weakly-typed language and a "native" operation on a type--a String class might support the multiplication operator (and give it semantics exactly like those in JavaScript for example--if the two strings are texutal representations of numbers, convert to the number and multiply; otherwise return an exception or NotaNumber (I cannot remember which).
In other words, a strongly typed language can be made into a weakly type language via extension.
Still, the characterization of a language as "strong" or "weak" or in between is still useful